summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorLoic GUEGAN <loic@Manzerbredes>2016-01-23 14:37:24 +0100
committerLoic GUEGAN <loic@Manzerbredes>2016-01-23 14:37:24 +0100
commit189f7a9ef4c6265dbac232e5c5685aebbbfc7c53 (patch)
treed397facc1e45cee4713ea95b0eaa4ffa9cbf0921 /server
parent2984adf171c49940e683fa997e8cdc60fcf1d60b (diff)
parenta44cc1d2e3c0f147e91a5c052ac7fd879e34e706 (diff)
Merge branch 'develop' of github.com:manzerbredes/istic-openstack into develop
Diffstat (limited to 'server')
-rw-r--r--server/composer.json5
-rw-r--r--server/composer.lock351
-rwxr-xr-xserver/composer.pharbin0 -> 1514291 bytes
-rw-r--r--server/vendor/autoload.php7
l---------server/vendor/bin/validate-json1
-rw-r--r--server/vendor/composer/ClassLoader.php413
-rw-r--r--server/vendor/composer/LICENSE21
-rw-r--r--server/vendor/composer/autoload_classmap.php9
-rw-r--r--server/vendor/composer/autoload_files.php12
-rw-r--r--server/vendor/composer/autoload_namespaces.php9
-rw-r--r--server/vendor/composer/autoload_psr4.php15
-rw-r--r--server/vendor/composer/autoload_real.php59
-rw-r--r--server/vendor/composer/installed.json344
-rw-r--r--server/vendor/guzzlehttp/guzzle/.travis.yml40
-rw-r--r--server/vendor/guzzlehttp/guzzle/CHANGELOG.md1203
-rw-r--r--server/vendor/guzzlehttp/guzzle/LICENSE19
-rw-r--r--server/vendor/guzzlehttp/guzzle/README.md90
-rw-r--r--server/vendor/guzzlehttp/guzzle/UPGRADING.md1203
-rw-r--r--server/vendor/guzzlehttp/guzzle/composer.json41
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Client.php397
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/ClientInterface.php84
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php277
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php84
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php87
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php72
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php404
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php7
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php7
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php37
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php4
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php188
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Exception/SeekException.php27
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php7
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php4
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php4
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php531
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php27
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php45
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php197
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php87
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php176
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php55
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php458
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/HandlerStack.php273
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/MessageFormatter.php182
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Middleware.php249
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/Pool.php123
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php112
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php231
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/RequestOptions.php244
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/RetryMiddleware.php111
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/TransferStats.php126
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/UriTemplate.php241
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/functions.php284
-rw-r--r--server/vendor/guzzlehttp/guzzle/src/functions_include.php6
-rw-r--r--server/vendor/guzzlehttp/promises/.gitignore11
-rw-r--r--server/vendor/guzzlehttp/promises/.travis.yml19
-rw-r--r--server/vendor/guzzlehttp/promises/CHANGELOG.md21
-rw-r--r--server/vendor/guzzlehttp/promises/LICENSE19
-rw-r--r--server/vendor/guzzlehttp/promises/Makefile13
-rw-r--r--server/vendor/guzzlehttp/promises/README.md501
-rw-r--r--server/vendor/guzzlehttp/promises/composer.json31
-rw-r--r--server/vendor/guzzlehttp/promises/phpunit.xml.dist17
-rw-r--r--server/vendor/guzzlehttp/promises/src/AggregateException.php16
-rw-r--r--server/vendor/guzzlehttp/promises/src/CancellationException.php9
-rw-r--r--server/vendor/guzzlehttp/promises/src/EachPromise.php207
-rw-r--r--server/vendor/guzzlehttp/promises/src/FulfilledPromise.php80
-rw-r--r--server/vendor/guzzlehttp/promises/src/Promise.php268
-rw-r--r--server/vendor/guzzlehttp/promises/src/PromiseInterface.php93
-rw-r--r--server/vendor/guzzlehttp/promises/src/PromisorInterface.php15
-rw-r--r--server/vendor/guzzlehttp/promises/src/RejectedPromise.php84
-rw-r--r--server/vendor/guzzlehttp/promises/src/RejectionException.php47
-rw-r--r--server/vendor/guzzlehttp/promises/src/TaskQueue.php79
-rw-r--r--server/vendor/guzzlehttp/promises/src/functions.php495
-rw-r--r--server/vendor/guzzlehttp/promises/src/functions_include.php6
-rw-r--r--server/vendor/guzzlehttp/promises/tests/AggregateExceptionTest.php14
-rw-r--r--server/vendor/guzzlehttp/promises/tests/EachPromiseTest.php294
-rw-r--r--server/vendor/guzzlehttp/promises/tests/FulfilledPromiseTest.php108
-rw-r--r--server/vendor/guzzlehttp/promises/tests/NotPromiseInstance.php50
-rw-r--r--server/vendor/guzzlehttp/promises/tests/PromiseTest.php579
-rw-r--r--server/vendor/guzzlehttp/promises/tests/RejectedPromiseTest.php143
-rw-r--r--server/vendor/guzzlehttp/promises/tests/RejectionExceptionTest.php47
-rw-r--r--server/vendor/guzzlehttp/promises/tests/TaskQueueTest.php31
-rw-r--r--server/vendor/guzzlehttp/promises/tests/Thennable.php24
-rw-r--r--server/vendor/guzzlehttp/promises/tests/bootstrap.php4
-rw-r--r--server/vendor/guzzlehttp/promises/tests/functionsTest.php694
-rw-r--r--server/vendor/guzzlehttp/psr7/.gitignore11
-rw-r--r--server/vendor/guzzlehttp/psr7/.travis.yml20
-rw-r--r--server/vendor/guzzlehttp/psr7/CHANGELOG.md32
-rw-r--r--server/vendor/guzzlehttp/psr7/LICENSE19
-rw-r--r--server/vendor/guzzlehttp/psr7/Makefile13
-rw-r--r--server/vendor/guzzlehttp/psr7/README.md580
-rw-r--r--server/vendor/guzzlehttp/psr7/composer.json35
-rw-r--r--server/vendor/guzzlehttp/psr7/phpunit.xml.dist17
-rw-r--r--server/vendor/guzzlehttp/psr7/src/AppendStream.php233
-rw-r--r--server/vendor/guzzlehttp/psr7/src/BufferStream.php137
-rw-r--r--server/vendor/guzzlehttp/psr7/src/CachingStream.php135
-rw-r--r--server/vendor/guzzlehttp/psr7/src/DroppingStream.php42
-rw-r--r--server/vendor/guzzlehttp/psr7/src/FnStream.php149
-rw-r--r--server/vendor/guzzlehttp/psr7/src/InflateStream.php29
-rw-r--r--server/vendor/guzzlehttp/psr7/src/LazyOpenStream.php39
-rw-r--r--server/vendor/guzzlehttp/psr7/src/LimitStream.php155
-rw-r--r--server/vendor/guzzlehttp/psr7/src/MessageTrait.php158
-rw-r--r--server/vendor/guzzlehttp/psr7/src/MultipartStream.php153
-rw-r--r--server/vendor/guzzlehttp/psr7/src/NoSeekStream.php22
-rw-r--r--server/vendor/guzzlehttp/psr7/src/PumpStream.php165
-rw-r--r--server/vendor/guzzlehttp/psr7/src/Request.php149
-rw-r--r--server/vendor/guzzlehttp/psr7/src/Response.php130
-rw-r--r--server/vendor/guzzlehttp/psr7/src/Stream.php245
-rw-r--r--server/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php149
-rw-r--r--server/vendor/guzzlehttp/psr7/src/StreamWrapper.php121
-rw-r--r--server/vendor/guzzlehttp/psr7/src/Uri.php599
-rw-r--r--server/vendor/guzzlehttp/psr7/src/functions.php802
-rw-r--r--server/vendor/guzzlehttp/psr7/src/functions_include.php6
-rw-r--r--server/vendor/guzzlehttp/psr7/tests/AppendStreamTest.php186
-rw-r--r--server/vendor/guzzlehttp/psr7/tests/BufferStreamTest.php63
-rw-r--r--server/vendor/guzzlehttp/psr7/tests/CachingStreamTest.php166
-rw-r--r--server/vendor/guzzlehttp/psr7/tests/DroppingStreamTest.php26
-rw-r--r--server/vendor/guzzlehttp/psr7/tests/FnStreamTest.php90
-rw-r--r--server/vendor/guzzlehttp/psr7/tests/FunctionsTest.php586
-rw-r--r--server/vendor/guzzlehttp/psr7/tests/InflateStreamTest.php16
-rw-r--r--server/vendor/guzzlehttp/psr7/tests/LazyOpenStreamTest.php64
-rw-r--r--server/vendor/guzzlehttp/psr7/tests/LimitStreamTest.php166
-rw-r--r--server/vendor/guzzlehttp/psr7/tests/MultipartStreamTest.php214
-rw-r--r--server/vendor/guzzlehttp/psr7/tests/NoSeekStreamTest.php40
-rw-r--r--server/vendor/guzzlehttp/psr7/tests/PumpStreamTest.php72
-rw-r--r--server/vendor/guzzlehttp/psr7/tests/RequestTest.php157
-rw-r--r--server/vendor/guzzlehttp/psr7/tests/ResponseTest.php146
-rw-r--r--server/vendor/guzzlehttp/psr7/tests/StreamDecoratorTraitTest.php137
-rw-r--r--server/vendor/guzzlehttp/psr7/tests/StreamTest.php161
-rw-r--r--server/vendor/guzzlehttp/psr7/tests/StreamWrapperTest.php100
-rw-r--r--server/vendor/guzzlehttp/psr7/tests/UriTest.php247
-rw-r--r--server/vendor/guzzlehttp/psr7/tests/bootstrap.php11
-rw-r--r--server/vendor/justinrainbow/json-schema/.gitattributes5
-rw-r--r--server/vendor/justinrainbow/json-schema/LICENSE29
-rw-r--r--server/vendor/justinrainbow/json-schema/README.md55
-rwxr-xr-xserver/vendor/justinrainbow/json-schema/bin/validate-json245
-rw-r--r--server/vendor/justinrainbow/json-schema/composer.json58
-rw-r--r--server/vendor/justinrainbow/json-schema/phpunit.xml.dist26
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php112
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php291
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php60
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php46
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php81
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php181
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php83
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php149
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php37
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php57
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php145
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php307
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php17
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.php17
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSourceUriException.php17
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php40
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.php17
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.php17
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/RefResolver.php277
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/AbstractRetriever.php29
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/Curl.php79
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php87
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/PredefinedArray.php54
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/UriRetrieverInterface.php32
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php157
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php289
-rw-r--r--server/vendor/justinrainbow/json-schema/src/JsonSchema/Validator.php40
m---------server/vendor/php-opencloud/openstack0
-rw-r--r--server/vendor/psr/http-message/LICENSE19
-rw-r--r--server/vendor/psr/http-message/README.md13
-rw-r--r--server/vendor/psr/http-message/composer.json25
-rw-r--r--server/vendor/psr/http-message/src/MessageInterface.php187
-rw-r--r--server/vendor/psr/http-message/src/RequestInterface.php129
-rw-r--r--server/vendor/psr/http-message/src/ResponseInterface.php68
-rw-r--r--server/vendor/psr/http-message/src/ServerRequestInterface.php261
-rw-r--r--server/vendor/psr/http-message/src/StreamInterface.php158
-rw-r--r--server/vendor/psr/http-message/src/UploadedFileInterface.php123
-rw-r--r--server/vendor/psr/http-message/src/UriInterface.php323
177 files changed, 24744 insertions, 0 deletions
diff --git a/server/composer.json b/server/composer.json
new file mode 100644
index 0000000..d5e2dbc
--- /dev/null
+++ b/server/composer.json
@@ -0,0 +1,5 @@
+{
+ "require": {
+ "php-opencloud/openstack": "dev-master"
+ }
+}
diff --git a/server/composer.lock b/server/composer.lock
new file mode 100644
index 0000000..e8976df
--- /dev/null
+++ b/server/composer.lock
@@ -0,0 +1,351 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+ "This file is @generated automatically"
+ ],
+ "hash": "e7cbd5d3df36fb1a3f3378b837068196",
+ "content-hash": "125e4702f7a417475a4150c889ac6c3d",
+ "packages": [
+ {
+ "name": "guzzlehttp/guzzle",
+ "version": "6.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "c6851d6e48f63b69357cbfa55bca116448140e0c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/c6851d6e48f63b69357cbfa55bca116448140e0c",
+ "reference": "c6851d6e48f63b69357cbfa55bca116448140e0c",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/promises": "~1.0",
+ "guzzlehttp/psr7": "~1.1",
+ "php": ">=5.5.0"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "phpunit/phpunit": "~4.0",
+ "psr/log": "~1.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "6.1-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "rest",
+ "web service"
+ ],
+ "time": "2015-11-23 00:47:50"
+ },
+ {
+ "name": "guzzlehttp/promises",
+ "version": "1.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/promises.git",
+ "reference": "b1e1c0d55f8083c71eda2c28c12a228d708294ea"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/b1e1c0d55f8083c71eda2c28c12a228d708294ea",
+ "reference": "b1e1c0d55f8083c71eda2c28c12a228d708294ea",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Promise\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Guzzle promises library",
+ "keywords": [
+ "promise"
+ ],
+ "time": "2015-10-15 22:28:00"
+ },
+ {
+ "name": "guzzlehttp/psr7",
+ "version": "1.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/psr7.git",
+ "reference": "4d0bdbe1206df7440219ce14c972aa57cc5e4982"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/4d0bdbe1206df7440219ce14c972aa57cc5e4982",
+ "reference": "4d0bdbe1206df7440219ce14c972aa57cc5e4982",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4.0",
+ "psr/http-message": "~1.0"
+ },
+ "provide": {
+ "psr/http-message-implementation": "1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Psr7\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "PSR-7 message implementation",
+ "keywords": [
+ "http",
+ "message",
+ "stream",
+ "uri"
+ ],
+ "time": "2015-11-03 01:34:55"
+ },
+ {
+ "name": "justinrainbow/json-schema",
+ "version": "v1.6.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/justinrainbow/json-schema.git",
+ "reference": "f9e27c3e202faf14fd581ef41355d83bb4b7eb7d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/f9e27c3e202faf14fd581ef41355d83bb4b7eb7d",
+ "reference": "f9e27c3e202faf14fd581ef41355d83bb4b7eb7d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.2"
+ },
+ "require-dev": {
+ "json-schema/json-schema-test-suite": "1.1.0",
+ "phpdocumentor/phpdocumentor": "~2",
+ "phpunit/phpunit": "~3.7"
+ },
+ "bin": [
+ "bin/validate-json"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.4.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "JsonSchema\\": "src/JsonSchema/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Bruno Prieto Reis",
+ "email": "bruno.p.reis@gmail.com"
+ },
+ {
+ "name": "Justin Rainbow",
+ "email": "justin.rainbow@gmail.com"
+ },
+ {
+ "name": "Igor Wiedler",
+ "email": "igor@wiedler.ch"
+ },
+ {
+ "name": "Robert Schönthal",
+ "email": "seroscho@googlemail.com"
+ }
+ ],
+ "description": "A library to validate a json schema.",
+ "homepage": "https://github.com/justinrainbow/json-schema",
+ "keywords": [
+ "json",
+ "schema"
+ ],
+ "time": "2016-01-06 14:37:04"
+ },
+ {
+ "name": "php-opencloud/openstack",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-opencloud/openstack.git",
+ "reference": "8a6ec703597f0440e558d8f1f21b2ff303117dbd"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-opencloud/openstack/zipball/8a6ec703597f0440e558d8f1f21b2ff303117dbd",
+ "reference": "8a6ec703597f0440e558d8f1f21b2ff303117dbd",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/guzzle": "~6.1",
+ "justinrainbow/json-schema": "~1.3",
+ "php": ">=5.6"
+ },
+ "require-dev": {
+ "fabpot/php-cs-fixer": "~1.0",
+ "jakub-onderka/php-parallel-lint": "0.*",
+ "phpspec/prophecy-phpunit": "~1.0",
+ "phpunit/phpunit": "~4.0",
+ "psr/log": "~1.0",
+ "sami/sami": "dev-master",
+ "satooshi/php-coveralls": "~1.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "OpenStack\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "authors": [
+ {
+ "name": "Jamie Hannaford",
+ "email": "jamie.hannaford@rackspace.com",
+ "homepage": "https://github.com/jamiehannaford"
+ }
+ ],
+ "time": "2016-01-20 12:27:59"
+ },
+ {
+ "name": "psr/http-message",
+ "version": "1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-message.git",
+ "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298",
+ "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP messages",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "time": "2015-05-04 20:22:00"
+ }
+ ],
+ "packages-dev": [],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": {
+ "php-opencloud/openstack": 20
+ },
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": [],
+ "platform-dev": []
+}
diff --git a/server/composer.phar b/server/composer.phar
new file mode 100755
index 0000000..0281237
--- /dev/null
+++ b/server/composer.phar
Binary files differ
diff --git a/server/vendor/autoload.php b/server/vendor/autoload.php
new file mode 100644
index 0000000..9566096
--- /dev/null
+++ b/server/vendor/autoload.php
@@ -0,0 +1,7 @@
+<?php
+
+// autoload.php @generated by Composer
+
+require_once __DIR__ . '/composer' . '/autoload_real.php';
+
+return ComposerAutoloaderInit6278e204890e617cb73cd66b51c1141f::getLoader();
diff --git a/server/vendor/bin/validate-json b/server/vendor/bin/validate-json
new file mode 120000
index 0000000..141e251
--- /dev/null
+++ b/server/vendor/bin/validate-json
@@ -0,0 +1 @@
+../justinrainbow/json-schema/bin/validate-json \ No newline at end of file
diff --git a/server/vendor/composer/ClassLoader.php b/server/vendor/composer/ClassLoader.php
new file mode 100644
index 0000000..ff6ecfb
--- /dev/null
+++ b/server/vendor/composer/ClassLoader.php
@@ -0,0 +1,413 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ * Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Autoload;
+
+/**
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
+ *
+ * $loader = new \Composer\Autoload\ClassLoader();
+ *
+ * // register classes with namespaces
+ * $loader->add('Symfony\Component', __DIR__.'/component');
+ * $loader->add('Symfony', __DIR__.'/framework');
+ *
+ * // activate the autoloader
+ * $loader->register();
+ *
+ * // to enable searching the include path (eg. for PEAR packages)
+ * $loader->setUseIncludePath(true);
+ *
+ * In this example, if you try to use a class in the Symfony\Component
+ * namespace or one of its children (Symfony\Component\Console for instance),
+ * the autoloader will first look for the class under the component/
+ * directory, and it will then fallback to the framework/ directory if not
+ * found before giving up.
+ *
+ * This class is loosely based on the Symfony UniversalClassLoader.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ * @see http://www.php-fig.org/psr/psr-0/
+ * @see http://www.php-fig.org/psr/psr-4/
+ */
+class ClassLoader
+{
+ // PSR-4
+ private $prefixLengthsPsr4 = array();
+ private $prefixDirsPsr4 = array();
+ private $fallbackDirsPsr4 = array();
+
+ // PSR-0
+ private $prefixesPsr0 = array();
+ private $fallbackDirsPsr0 = array();
+
+ private $useIncludePath = false;
+ private $classMap = array();
+
+ private $classMapAuthoritative = false;
+
+ public function getPrefixes()
+ {
+ if (!empty($this->prefixesPsr0)) {
+ return call_user_func_array('array_merge', $this->prefixesPsr0);
+ }
+
+ return array();
+ }
+
+ public function getPrefixesPsr4()
+ {
+ return $this->prefixDirsPsr4;
+ }
+
+ public function getFallbackDirs()
+ {
+ return $this->fallbackDirsPsr0;
+ }
+
+ public function getFallbackDirsPsr4()
+ {
+ return $this->fallbackDirsPsr4;
+ }
+
+ public function getClassMap()
+ {
+ return $this->classMap;
+ }
+
+ /**
+ * @param array $classMap Class to filename map
+ */
+ public function addClassMap(array $classMap)
+ {
+ if ($this->classMap) {
+ $this->classMap = array_merge($this->classMap, $classMap);
+ } else {
+ $this->classMap = $classMap;
+ }
+ }
+
+ /**
+ * Registers a set of PSR-0 directories for a given prefix, either
+ * appending or prepending to the ones previously set for this prefix.
+ *
+ * @param string $prefix The prefix
+ * @param array|string $paths The PSR-0 root directories
+ * @param bool $prepend Whether to prepend the directories
+ */
+ public function add($prefix, $paths, $prepend = false)
+ {
+ if (!$prefix) {
+ if ($prepend) {
+ $this->fallbackDirsPsr0 = array_merge(
+ (array) $paths,
+ $this->fallbackDirsPsr0
+ );
+ } else {
+ $this->fallbackDirsPsr0 = array_merge(
+ $this->fallbackDirsPsr0,
+ (array) $paths
+ );
+ }
+
+ return;
+ }
+
+ $first = $prefix[0];
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
+ $this->prefixesPsr0[$first][$prefix] = (array) $paths;
+
+ return;
+ }
+ if ($prepend) {
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
+ (array) $paths,
+ $this->prefixesPsr0[$first][$prefix]
+ );
+ } else {
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
+ $this->prefixesPsr0[$first][$prefix],
+ (array) $paths
+ );
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace, either
+ * appending or prepending to the ones previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param array|string $paths The PSR-4 base directories
+ * @param bool $prepend Whether to prepend the directories
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function addPsr4($prefix, $paths, $prepend = false)
+ {
+ if (!$prefix) {
+ // Register directories for the root namespace.
+ if ($prepend) {
+ $this->fallbackDirsPsr4 = array_merge(
+ (array) $paths,
+ $this->fallbackDirsPsr4
+ );
+ } else {
+ $this->fallbackDirsPsr4 = array_merge(
+ $this->fallbackDirsPsr4,
+ (array) $paths
+ );
+ }
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
+ // Register directories for a new namespace.
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ } elseif ($prepend) {
+ // Prepend directories for an already registered namespace.
+ $this->prefixDirsPsr4[$prefix] = array_merge(
+ (array) $paths,
+ $this->prefixDirsPsr4[$prefix]
+ );
+ } else {
+ // Append directories for an already registered namespace.
+ $this->prefixDirsPsr4[$prefix] = array_merge(
+ $this->prefixDirsPsr4[$prefix],
+ (array) $paths
+ );
+ }
+ }
+
+ /**
+ * Registers a set of PSR-0 directories for a given prefix,
+ * replacing any others previously set for this prefix.
+ *
+ * @param string $prefix The prefix
+ * @param array|string $paths The PSR-0 base directories
+ */
+ public function set($prefix, $paths)
+ {
+ if (!$prefix) {
+ $this->fallbackDirsPsr0 = (array) $paths;
+ } else {
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace,
+ * replacing any others previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param array|string $paths The PSR-4 base directories
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function setPsr4($prefix, $paths)
+ {
+ if (!$prefix) {
+ $this->fallbackDirsPsr4 = (array) $paths;
+ } else {
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ }
+ }
+
+ /**
+ * Turns on searching the include path for class files.
+ *
+ * @param bool $useIncludePath
+ */
+ public function setUseIncludePath($useIncludePath)
+ {
+ $this->useIncludePath = $useIncludePath;
+ }
+
+ /**
+ * Can be used to check if the autoloader uses the include path to check
+ * for classes.
+ *
+ * @return bool
+ */
+ public function getUseIncludePath()
+ {
+ return $this->useIncludePath;
+ }
+
+ /**
+ * Turns off searching the prefix and fallback directories for classes
+ * that have not been registered with the class map.
+ *
+ * @param bool $classMapAuthoritative
+ */
+ public function setClassMapAuthoritative($classMapAuthoritative)
+ {
+ $this->classMapAuthoritative = $classMapAuthoritative;
+ }
+
+ /**
+ * Should class lookup fail if not found in the current class map?
+ *
+ * @return bool
+ */
+ public function isClassMapAuthoritative()
+ {
+ return $this->classMapAuthoritative;
+ }
+
+ /**
+ * Registers this instance as an autoloader.
+ *
+ * @param bool $prepend Whether to prepend the autoloader or not
+ */
+ public function register($prepend = false)
+ {
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+ }
+
+ /**
+ * Unregisters this instance as an autoloader.
+ */
+ public function unregister()
+ {
+ spl_autoload_unregister(array($this, 'loadClass'));
+ }
+
+ /**
+ * Loads the given class or interface.
+ *
+ * @param string $class The name of the class
+ * @return bool|null True if loaded, null otherwise
+ */
+ public function loadClass($class)
+ {
+ if ($file = $this->findFile($class)) {
+ includeFile($file);
+
+ return true;
+ }
+ }
+
+ /**
+ * Finds the path to the file where the class is defined.
+ *
+ * @param string $class The name of the class
+ *
+ * @return string|false The path if found, false otherwise
+ */
+ public function findFile($class)
+ {
+ // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
+ if ('\\' == $class[0]) {
+ $class = substr($class, 1);
+ }
+
+ // class map lookup
+ if (isset($this->classMap[$class])) {
+ return $this->classMap[$class];
+ }
+ if ($this->classMapAuthoritative) {
+ return false;
+ }
+
+ $file = $this->findFileWithExtension($class, '.php');
+
+ // Search for Hack files if we are running on HHVM
+ if ($file === null && defined('HHVM_VERSION')) {
+ $file = $this->findFileWithExtension($class, '.hh');
+ }
+
+ if ($file === null) {
+ // Remember that this class does not exist.
+ return $this->classMap[$class] = false;
+ }
+
+ return $file;
+ }
+
+ private function findFileWithExtension($class, $ext)
+ {
+ // PSR-4 lookup
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
+
+ $first = $class[0];
+ if (isset($this->prefixLengthsPsr4[$first])) {
+ foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
+ if (0 === strpos($class, $prefix)) {
+ foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
+ return $file;
+ }
+ }
+ }
+ }
+ }
+
+ // PSR-4 fallback dirs
+ foreach ($this->fallbackDirsPsr4 as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
+ return $file;
+ }
+ }
+
+ // PSR-0 lookup
+ if (false !== $pos = strrpos($class, '\\')) {
+ // namespaced class name
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
+ } else {
+ // PEAR-like class name
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
+ }
+
+ if (isset($this->prefixesPsr0[$first])) {
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
+ if (0 === strpos($class, $prefix)) {
+ foreach ($dirs as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+ return $file;
+ }
+ }
+ }
+ }
+ }
+
+ // PSR-0 fallback dirs
+ foreach ($this->fallbackDirsPsr0 as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+ return $file;
+ }
+ }
+
+ // PSR-0 include paths.
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
+ return $file;
+ }
+ }
+}
+
+/**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ */
+function includeFile($file)
+{
+ include $file;
+}
diff --git a/server/vendor/composer/LICENSE b/server/vendor/composer/LICENSE
new file mode 100644
index 0000000..c8d57af
--- /dev/null
+++ b/server/vendor/composer/LICENSE
@@ -0,0 +1,21 @@
+
+Copyright (c) 2015 Nils Adermann, Jordi Boggiano
+
+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/server/vendor/composer/autoload_classmap.php b/server/vendor/composer/autoload_classmap.php
new file mode 100644
index 0000000..7a91153
--- /dev/null
+++ b/server/vendor/composer/autoload_classmap.php
@@ -0,0 +1,9 @@
+<?php
+
+// autoload_classmap.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+);
diff --git a/server/vendor/composer/autoload_files.php b/server/vendor/composer/autoload_files.php
new file mode 100644
index 0000000..dd37d85
--- /dev/null
+++ b/server/vendor/composer/autoload_files.php
@@ -0,0 +1,12 @@
+<?php
+
+// autoload_files.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+ 'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
+ 'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
+ '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
+);
diff --git a/server/vendor/composer/autoload_namespaces.php b/server/vendor/composer/autoload_namespaces.php
new file mode 100644
index 0000000..b7fc012
--- /dev/null
+++ b/server/vendor/composer/autoload_namespaces.php
@@ -0,0 +1,9 @@
+<?php
+
+// autoload_namespaces.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+);
diff --git a/server/vendor/composer/autoload_psr4.php b/server/vendor/composer/autoload_psr4.php
new file mode 100644
index 0000000..0ba35e5
--- /dev/null
+++ b/server/vendor/composer/autoload_psr4.php
@@ -0,0 +1,15 @@
+<?php
+
+// autoload_psr4.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+ 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
+ 'OpenStack\\' => array($vendorDir . '/php-opencloud/openstack/src'),
+ 'JsonSchema\\' => array($vendorDir . '/justinrainbow/json-schema/src/JsonSchema'),
+ 'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
+ 'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
+ 'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
+);
diff --git a/server/vendor/composer/autoload_real.php b/server/vendor/composer/autoload_real.php
new file mode 100644
index 0000000..c1db66f
--- /dev/null
+++ b/server/vendor/composer/autoload_real.php
@@ -0,0 +1,59 @@
+<?php
+
+// autoload_real.php @generated by Composer
+
+class ComposerAutoloaderInit6278e204890e617cb73cd66b51c1141f
+{
+ private static $loader;
+
+ public static function loadClassLoader($class)
+ {
+ if ('Composer\Autoload\ClassLoader' === $class) {
+ require __DIR__ . '/ClassLoader.php';
+ }
+ }
+
+ public static function getLoader()
+ {
+ if (null !== self::$loader) {
+ return self::$loader;
+ }
+
+ spl_autoload_register(array('ComposerAutoloaderInit6278e204890e617cb73cd66b51c1141f', 'loadClassLoader'), true, true);
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader();
+ spl_autoload_unregister(array('ComposerAutoloaderInit6278e204890e617cb73cd66b51c1141f', 'loadClassLoader'));
+
+ $map = require __DIR__ . '/autoload_namespaces.php';
+ foreach ($map as $namespace => $path) {
+ $loader->set($namespace, $path);
+ }
+
+ $map = require __DIR__ . '/autoload_psr4.php';
+ foreach ($map as $namespace => $path) {
+ $loader->setPsr4($namespace, $path);
+ }
+
+ $classMap = require __DIR__ . '/autoload_classmap.php';
+ if ($classMap) {
+ $loader->addClassMap($classMap);
+ }
+
+ $loader->register(true);
+
+ $includeFiles = require __DIR__ . '/autoload_files.php';
+ foreach ($includeFiles as $fileIdentifier => $file) {
+ composerRequire6278e204890e617cb73cd66b51c1141f($fileIdentifier, $file);
+ }
+
+ return $loader;
+ }
+}
+
+function composerRequire6278e204890e617cb73cd66b51c1141f($fileIdentifier, $file)
+{
+ if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
+ require $file;
+
+ $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
+ }
+}
diff --git a/server/vendor/composer/installed.json b/server/vendor/composer/installed.json
new file mode 100644
index 0000000..8e3f2ec
--- /dev/null
+++ b/server/vendor/composer/installed.json
@@ -0,0 +1,344 @@
+[
+ {
+ "name": "justinrainbow/json-schema",
+ "version": "v1.6.0",
+ "version_normalized": "1.6.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/justinrainbow/json-schema.git",
+ "reference": "f9e27c3e202faf14fd581ef41355d83bb4b7eb7d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/f9e27c3e202faf14fd581ef41355d83bb4b7eb7d",
+ "reference": "f9e27c3e202faf14fd581ef41355d83bb4b7eb7d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.2"
+ },
+ "require-dev": {
+ "json-schema/json-schema-test-suite": "1.1.0",
+ "phpdocumentor/phpdocumentor": "~2",
+ "phpunit/phpunit": "~3.7"
+ },
+ "time": "2016-01-06 14:37:04",
+ "bin": [
+ "bin/validate-json"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.4.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "JsonSchema\\": "src/JsonSchema/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Bruno Prieto Reis",
+ "email": "bruno.p.reis@gmail.com"
+ },
+ {
+ "name": "Justin Rainbow",
+ "email": "justin.rainbow@gmail.com"
+ },
+ {
+ "name": "Igor Wiedler",
+ "email": "igor@wiedler.ch"
+ },
+ {
+ "name": "Robert Schönthal",
+ "email": "seroscho@googlemail.com"
+ }
+ ],
+ "description": "A library to validate a json schema.",
+ "homepage": "https://github.com/justinrainbow/json-schema",
+ "keywords": [
+ "json",
+ "schema"
+ ]
+ },
+ {
+ "name": "guzzlehttp/promises",
+ "version": "1.0.3",
+ "version_normalized": "1.0.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/promises.git",
+ "reference": "b1e1c0d55f8083c71eda2c28c12a228d708294ea"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/b1e1c0d55f8083c71eda2c28c12a228d708294ea",
+ "reference": "b1e1c0d55f8083c71eda2c28c12a228d708294ea",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "time": "2015-10-15 22:28:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Promise\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Guzzle promises library",
+ "keywords": [
+ "promise"
+ ]
+ },
+ {
+ "name": "psr/http-message",
+ "version": "1.0",
+ "version_normalized": "1.0.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-message.git",
+ "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298",
+ "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "time": "2015-05-04 20:22:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP messages",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr",
+ "psr-7",
+ "request",
+ "response"
+ ]
+ },
+ {
+ "name": "guzzlehttp/psr7",
+ "version": "1.2.1",
+ "version_normalized": "1.2.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/psr7.git",
+ "reference": "4d0bdbe1206df7440219ce14c972aa57cc5e4982"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/4d0bdbe1206df7440219ce14c972aa57cc5e4982",
+ "reference": "4d0bdbe1206df7440219ce14c972aa57cc5e4982",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4.0",
+ "psr/http-message": "~1.0"
+ },
+ "provide": {
+ "psr/http-message-implementation": "1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "time": "2015-11-03 01:34:55",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Psr7\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "PSR-7 message implementation",
+ "keywords": [
+ "http",
+ "message",
+ "stream",
+ "uri"
+ ]
+ },
+ {
+ "name": "guzzlehttp/guzzle",
+ "version": "6.1.1",
+ "version_normalized": "6.1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "c6851d6e48f63b69357cbfa55bca116448140e0c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/c6851d6e48f63b69357cbfa55bca116448140e0c",
+ "reference": "c6851d6e48f63b69357cbfa55bca116448140e0c",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/promises": "~1.0",
+ "guzzlehttp/psr7": "~1.1",
+ "php": ">=5.5.0"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "phpunit/phpunit": "~4.0",
+ "psr/log": "~1.0"
+ },
+ "time": "2015-11-23 00:47:50",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "6.1-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "rest",
+ "web service"
+ ]
+ },
+ {
+ "name": "php-opencloud/openstack",
+ "version": "dev-master",
+ "version_normalized": "9999999-dev",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-opencloud/openstack.git",
+ "reference": "8a6ec703597f0440e558d8f1f21b2ff303117dbd"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-opencloud/openstack/zipball/8a6ec703597f0440e558d8f1f21b2ff303117dbd",
+ "reference": "8a6ec703597f0440e558d8f1f21b2ff303117dbd",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/guzzle": "~6.1",
+ "justinrainbow/json-schema": "~1.3",
+ "php": ">=5.6"
+ },
+ "require-dev": {
+ "fabpot/php-cs-fixer": "~1.0",
+ "jakub-onderka/php-parallel-lint": "0.*",
+ "phpspec/prophecy-phpunit": "~1.0",
+ "phpunit/phpunit": "~4.0",
+ "psr/log": "~1.0",
+ "sami/sami": "dev-master",
+ "satooshi/php-coveralls": "~1.0"
+ },
+ "time": "2016-01-20 12:27:59",
+ "type": "library",
+ "installation-source": "source",
+ "autoload": {
+ "psr-4": {
+ "OpenStack\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "authors": [
+ {
+ "name": "Jamie Hannaford",
+ "email": "jamie.hannaford@rackspace.com",
+ "homepage": "https://github.com/jamiehannaford"
+ }
+ ]
+ }
+]
diff --git a/server/vendor/guzzlehttp/guzzle/.travis.yml b/server/vendor/guzzlehttp/guzzle/.travis.yml
new file mode 100644
index 0000000..d2060f4
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/.travis.yml
@@ -0,0 +1,40 @@
+language: php
+
+sudo: false
+
+php:
+ - 5.5
+ - 5.6
+ - 7.0
+ - hhvm
+
+before_script:
+ - curl --version
+ - composer self-update
+ - composer install --no-interaction --prefer-source --dev
+ - ~/.nvm/nvm.sh install v0.6.14
+ - ~/.nvm/nvm.sh run v0.6.14
+
+script: make test
+
+matrix:
+ allow_failures:
+ - php: hhvm
+ - php: 7.0
+ fast_finish: true
+
+before_deploy:
+ - make package
+
+deploy:
+ provider: releases
+ api_key:
+ secure: UpypqlYgsU68QT/x40YzhHXvzWjFwCNo9d+G8KAdm7U9+blFfcWhV1aMdzugvPMl6woXgvJj7qHq5tAL4v6oswCORhpSBfLgOQVFaica5LiHsvWlAedOhxGmnJqMTwuepjBCxXhs3+I8Kof1n4oUL9gKytXjOVCX/f7XU1HiinU=
+ file:
+ - build/artifacts/guzzle.phar
+ - build/artifacts/guzzle.zip
+ on:
+ repo: guzzle/guzzle
+ tags: true
+ all_branches: true
+ php: 5.5
diff --git a/server/vendor/guzzlehttp/guzzle/CHANGELOG.md b/server/vendor/guzzlehttp/guzzle/CHANGELOG.md
new file mode 100644
index 0000000..5b7669b
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/CHANGELOG.md
@@ -0,0 +1,1203 @@
+# CHANGELOG
+
+## 6.1.1 - 2015-11-22
+
+* Bug fix: Proxy::wrapSync() now correctly proxies to the appropriate handler
+ https://github.com/guzzle/guzzle/commit/911bcbc8b434adce64e223a6d1d14e9a8f63e4e4
+* Feature: HandlerStack is now more generic.
+ https://github.com/guzzle/guzzle/commit/f2102941331cda544745eedd97fc8fd46e1ee33e
+* Bug fix: setting verify to false in the StreamHandler now disables peer
+ verification. https://github.com/guzzle/guzzle/issues/1256
+* Feature: Middleware now uses an exception factory, including more error
+ context. https://github.com/guzzle/guzzle/pull/1282
+* Feature: better support for disabled functions.
+ https://github.com/guzzle/guzzle/pull/1287
+* Bug fix: fixed regression where MockHandler was not using `sink`.
+ https://github.com/guzzle/guzzle/pull/1292
+
+## 6.1.0 - 2015-09-08
+
+* Feature: Added the `on_stats` request option to provide access to transfer
+ statistics for requests. https://github.com/guzzle/guzzle/pull/1202
+* Feature: Added the ability to persist session cookies in CookieJars.
+ https://github.com/guzzle/guzzle/pull/1195
+* Feature: Some compatibility updates for Google APP Engine
+ https://github.com/guzzle/guzzle/pull/1216
+* Feature: Added support for NO_PROXY to prevent the use of a proxy based on
+ a simple set of rules. https://github.com/guzzle/guzzle/pull/1197
+* Feature: Cookies can now contain square brackets.
+ https://github.com/guzzle/guzzle/pull/1237
+* Bug fix: Now correctly parsing `=` inside of quotes in Cookies.
+ https://github.com/guzzle/guzzle/pull/1232
+* Bug fix: Cusotm cURL options now correctly override curl options of the
+ same name. https://github.com/guzzle/guzzle/pull/1221
+* Bug fix: Content-Type header is now added when using an explicitly provided
+ multipart body. https://github.com/guzzle/guzzle/pull/1218
+* Bug fix: Now ignoring Set-Cookie headers that have no name.
+* Bug fix: Reason phrase is no longer cast to an int in some cases in the
+ cURL handler. https://github.com/guzzle/guzzle/pull/1187
+* Bug fix: Remove the Authorization header when redirecting if the Host
+ header changes. https://github.com/guzzle/guzzle/pull/1207
+* Bug fix: Cookie path matching fixes
+ https://github.com/guzzle/guzzle/issues/1129
+* Bug fix: Fixing the cURL `body_as_string` setting
+ https://github.com/guzzle/guzzle/pull/1201
+* Bug fix: quotes are no longer stripped when parsing cookies.
+ https://github.com/guzzle/guzzle/issues/1172
+* Bug fix: `form_params` and `query` now always uses the `&` separator.
+ https://github.com/guzzle/guzzle/pull/1163
+* Bug fix: Adding a Content-Length to PHP stream wrapper requests if not set.
+ https://github.com/guzzle/guzzle/pull/1189
+
+## 6.0.2 - 2015-07-04
+
+* Fixed a memory leak in the curl handlers in which references to callbacks
+ were not being removed by `curl_reset`.
+* Cookies are now extracted properly before redirects.
+* Cookies now allow more character ranges.
+* Decoded Content-Encoding responses are now modified to correctly reflect
+ their state if the encoding was automatically removed by a handler. This
+ means that the `Content-Encoding` header may be removed an the
+ `Content-Length` modified to reflect the message size after removing the
+ encoding.
+* Added a more explicit error message when trying to use `form_params` and
+ `multipart` in the same request.
+* Several fixes for HHVM support.
+* Functions are now conditionally required using an additional level of
+ indirection to help with global Composer installations.
+
+## 6.0.1 - 2015-05-27
+
+* Fixed a bug with serializing the `query` request option where the `&`
+ separator was missing.
+* Added a better error message for when `body` is provided as an array. Please
+ use `form_params` or `multipart` instead.
+* Various doc fixes.
+
+## 6.0.0 - 2015-05-26
+
+* See the UPGRADING.md document for more information.
+* Added `multipart` and `form_params` request options.
+* Added `synchronous` request option.
+* Added the `on_headers` request option.
+* Fixed `expect` handling.
+* No longer adding default middlewares in the client ctor. These need to be
+ present on the provided handler in order to work.
+* Requests are no longer initiated when sending async requests with the
+ CurlMultiHandler. This prevents unexpected recursion from requests completing
+ while ticking the cURL loop.
+* Removed the semantics of setting `default` to `true`. This is no longer
+ required now that the cURL loop is not ticked for async requests.
+* Added request and response logging middleware.
+* No longer allowing self signed certificates when using the StreamHandler.
+* Ensuring that `sink` is valid if saving to a file.
+* Request exceptions now include a "handler context" which provides handler
+ specific contextual information.
+* Added `GuzzleHttp\RequestOptions` to allow request options to be applied
+ using constants.
+* `$maxHandles` has been removed from CurlMultiHandler.
+* `MultipartPostBody` is now part of the `guzzlehttp/psr7` package.
+
+## 5.3.0 - 2015-05-19
+
+* Mock now supports `save_to`
+* Marked `AbstractRequestEvent::getTransaction()` as public.
+* Fixed a bug in which multiple headers using different casing would overwrite
+ previous headers in the associative array.
+* Added `Utils::getDefaultHandler()`
+* Marked `GuzzleHttp\Client::getDefaultUserAgent` as deprecated.
+* URL scheme is now always lowercased.
+
+## 6.0.0-beta.1
+
+* Requires PHP >= 5.5
+* Updated to use PSR-7
+ * Requires immutable messages, which basically means an event based system
+ owned by a request instance is no longer possible.
+ * Utilizing the [Guzzle PSR-7 package](https://github.com/guzzle/psr7).
+ * Removed the dependency on `guzzlehttp/streams`. These stream abstractions
+ are available in the `guzzlehttp/psr7` package under the `GuzzleHttp\Psr7`
+ namespace.
+* Added middleware and handler system
+ * Replaced the Guzzle event and subscriber system with a middleware system.
+ * No longer depends on RingPHP, but rather places the HTTP handlers directly
+ in Guzzle, operating on PSR-7 messages.
+ * Retry logic is now encapsulated in `GuzzleHttp\Middleware::retry`, which
+ means the `guzzlehttp/retry-subscriber` is now obsolete.
+ * Mocking responses is now handled using `GuzzleHttp\Handler\MockHandler`.
+* Asynchronous responses
+ * No longer supports the `future` request option to send an async request.
+ Instead, use one of the `*Async` methods of a client (e.g., `requestAsync`,
+ `getAsync`, etc.).
+ * Utilizing `GuzzleHttp\Promise` instead of React's promise library to avoid
+ recursion required by chaining and forwarding react promises. See
+ https://github.com/guzzle/promises
+ * Added `requestAsync` and `sendAsync` to send request asynchronously.
+ * Added magic methods for `getAsync()`, `postAsync()`, etc. to send requests
+ asynchronously.
+* Request options
+ * POST and form updates
+ * Added the `form_fields` and `form_files` request options.
+ * Removed the `GuzzleHttp\Post` namespace.
+ * The `body` request option no longer accepts an array for POST requests.
+ * The `exceptions` request option has been deprecated in favor of the
+ `http_errors` request options.
+ * The `save_to` request option has been deprecated in favor of `sink` request
+ option.
+* Clients no longer accept an array of URI template string and variables for
+ URI variables. You will need to expand URI templates before passing them
+ into a client constructor or request method.
+* Client methods `get()`, `post()`, `put()`, `patch()`, `options()`, etc. are
+ now magic methods that will send synchronous requests.
+* Replaced `Utils.php` with plain functions in `functions.php`.
+* Removed `GuzzleHttp\Collection`.
+* Removed `GuzzleHttp\BatchResults`. Batched pool results are now returned as
+ an array.
+* Removed `GuzzleHttp\Query`. Query string handling is now handled using an
+ associative array passed into the `query` request option. The query string
+ is serialized using PHP's `http_build_query`. If you need more control, you
+ can pass the query string in as a string.
+* `GuzzleHttp\QueryParser` has been replaced with the
+ `GuzzleHttp\Psr7\parse_query`.
+
+## 5.2.0 - 2015-01-27
+
+* Added `AppliesHeadersInterface` to make applying headers to a request based
+ on the body more generic and not specific to `PostBodyInterface`.
+* Reduced the number of stack frames needed to send requests.
+* Nested futures are now resolved in the client rather than the RequestFsm
+* Finishing state transitions is now handled in the RequestFsm rather than the
+ RingBridge.
+* Added a guard in the Pool class to not use recursion for request retries.
+
+## 5.1.0 - 2014-12-19
+
+* Pool class no longer uses recursion when a request is intercepted.
+* The size of a Pool can now be dynamically adjusted using a callback.
+ See https://github.com/guzzle/guzzle/pull/943.
+* Setting a request option to `null` when creating a request with a client will
+ ensure that the option is not set. This allows you to overwrite default
+ request options on a per-request basis.
+ See https://github.com/guzzle/guzzle/pull/937.
+* Added the ability to limit which protocols are allowed for redirects by
+ specifying a `protocols` array in the `allow_redirects` request option.
+* Nested futures due to retries are now resolved when waiting for synchronous
+ responses. See https://github.com/guzzle/guzzle/pull/947.
+* `"0"` is now an allowed URI path. See
+ https://github.com/guzzle/guzzle/pull/935.
+* `Query` no longer typehints on the `$query` argument in the constructor,
+ allowing for strings and arrays.
+* Exceptions thrown in the `end` event are now correctly wrapped with Guzzle
+ specific exceptions if necessary.
+
+## 5.0.3 - 2014-11-03
+
+This change updates query strings so that they are treated as un-encoded values
+by default where the value represents an un-encoded value to send over the
+wire. A Query object then encodes the value before sending over the wire. This
+means that even value query string values (e.g., ":") are url encoded. This
+makes the Query class match PHP's http_build_query function. However, if you
+want to send requests over the wire using valid query string characters that do
+not need to be encoded, then you can provide a string to Url::setQuery() and
+pass true as the second argument to specify that the query string is a raw
+string that should not be parsed or encoded (unless a call to getQuery() is
+subsequently made, forcing the query-string to be converted into a Query
+object).
+
+## 5.0.2 - 2014-10-30
+
+* Added a trailing `\r\n` to multipart/form-data payloads. See
+ https://github.com/guzzle/guzzle/pull/871
+* Added a `GuzzleHttp\Pool::send()` convenience method to match the docs.
+* Status codes are now returned as integers. See
+ https://github.com/guzzle/guzzle/issues/881
+* No longer overwriting an existing `application/x-www-form-urlencoded` header
+ when sending POST requests, allowing for customized headers. See
+ https://github.com/guzzle/guzzle/issues/877
+* Improved path URL serialization.
+
+ * No longer double percent-encoding characters in the path or query string if
+ they are already encoded.
+ * Now properly encoding the supplied path to a URL object, instead of only
+ encoding ' ' and '?'.
+ * Note: This has been changed in 5.0.3 to now encode query string values by
+ default unless the `rawString` argument is provided when setting the query
+ string on a URL: Now allowing many more characters to be present in the
+ query string without being percent encoded. See http://tools.ietf.org/html/rfc3986#appendix-A
+
+## 5.0.1 - 2014-10-16
+
+Bugfix release.
+
+* Fixed an issue where connection errors still returned response object in
+ error and end events event though the response is unusable. This has been
+ corrected so that a response is not returned in the `getResponse` method of
+ these events if the response did not complete. https://github.com/guzzle/guzzle/issues/867
+* Fixed an issue where transfer statistics were not being populated in the
+ RingBridge. https://github.com/guzzle/guzzle/issues/866
+
+## 5.0.0 - 2014-10-12
+
+Adding support for non-blocking responses and some minor API cleanup.
+
+### New Features
+
+* Added support for non-blocking responses based on `guzzlehttp/guzzle-ring`.
+* Added a public API for creating a default HTTP adapter.
+* Updated the redirect plugin to be non-blocking so that redirects are sent
+ concurrently. Other plugins like this can now be updated to be non-blocking.
+* Added a "progress" event so that you can get upload and download progress
+ events.
+* Added `GuzzleHttp\Pool` which implements FutureInterface and transfers
+ requests concurrently using a capped pool size as efficiently as possible.
+* Added `hasListeners()` to EmitterInterface.
+* Removed `GuzzleHttp\ClientInterface::sendAll` and marked
+ `GuzzleHttp\Client::sendAll` as deprecated (it's still there, just not the
+ recommended way).
+
+### Breaking changes
+
+The breaking changes in this release are relatively minor. The biggest thing to
+look out for is that request and response objects no longer implement fluent
+interfaces.
+
+* Removed the fluent interfaces (i.e., `return $this`) from requests,
+ responses, `GuzzleHttp\Collection`, `GuzzleHttp\Url`,
+ `GuzzleHttp\Query`, `GuzzleHttp\Post\PostBody`, and
+ `GuzzleHttp\Cookie\SetCookie`. This blog post provides a good outline of
+ why I did this: http://ocramius.github.io/blog/fluent-interfaces-are-evil/.
+ This also makes the Guzzle message interfaces compatible with the current
+ PSR-7 message proposal.
+* Removed "functions.php", so that Guzzle is truly PSR-4 compliant. Except
+ for the HTTP request functions from function.php, these functions are now
+ implemented in `GuzzleHttp\Utils` using camelCase. `GuzzleHttp\json_decode`
+ moved to `GuzzleHttp\Utils::jsonDecode`. `GuzzleHttp\get_path` moved to
+ `GuzzleHttp\Utils::getPath`. `GuzzleHttp\set_path` moved to
+ `GuzzleHttp\Utils::setPath`. `GuzzleHttp\batch` should now be
+ `GuzzleHttp\Pool::batch`, which returns an `objectStorage`. Using functions.php
+ caused problems for many users: they aren't PSR-4 compliant, require an
+ explicit include, and needed an if-guard to ensure that the functions are not
+ declared multiple times.
+* Rewrote adapter layer.
+ * Removing all classes from `GuzzleHttp\Adapter`, these are now
+ implemented as callables that are stored in `GuzzleHttp\Ring\Client`.
+ * Removed the concept of "parallel adapters". Sending requests serially or
+ concurrently is now handled using a single adapter.
+ * Moved `GuzzleHttp\Adapter\Transaction` to `GuzzleHttp\Transaction`. The
+ Transaction object now exposes the request, response, and client as public
+ properties. The getters and setters have been removed.
+* Removed the "headers" event. This event was only useful for changing the
+ body a response once the headers of the response were known. You can implement
+ a similar behavior in a number of ways. One example might be to use a
+ FnStream that has access to the transaction being sent. For example, when the
+ first byte is written, you could check if the response headers match your
+ expectations, and if so, change the actual stream body that is being
+ written to.
+* Removed the `asArray` parameter from
+ `GuzzleHttp\Message\MessageInterface::getHeader`. If you want to get a header
+ value as an array, then use the newly added `getHeaderAsArray()` method of
+ `MessageInterface`. This change makes the Guzzle interfaces compatible with
+ the PSR-7 interfaces.
+* `GuzzleHttp\Message\MessageFactory` no longer allows subclasses to add
+ custom request options using double-dispatch (this was an implementation
+ detail). Instead, you should now provide an associative array to the
+ constructor which is a mapping of the request option name mapping to a
+ function that applies the option value to a request.
+* Removed the concept of "throwImmediately" from exceptions and error events.
+ This control mechanism was used to stop a transfer of concurrent requests
+ from completing. This can now be handled by throwing the exception or by
+ cancelling a pool of requests or each outstanding future request individually.
+* Updated to "GuzzleHttp\Streams" 3.0.
+ * `GuzzleHttp\Stream\StreamInterface::getContents()` no longer accepts a
+ `maxLen` parameter. This update makes the Guzzle streams project
+ compatible with the current PSR-7 proposal.
+ * `GuzzleHttp\Stream\Stream::__construct`,
+ `GuzzleHttp\Stream\Stream::factory`, and
+ `GuzzleHttp\Stream\Utils::create` no longer accept a size in the second
+ argument. They now accept an associative array of options, including the
+ "size" key and "metadata" key which can be used to provide custom metadata.
+
+## 4.2.2 - 2014-09-08
+
+* Fixed a memory leak in the CurlAdapter when reusing cURL handles.
+* No longer using `request_fulluri` in stream adapter proxies.
+* Relative redirects are now based on the last response, not the first response.
+
+## 4.2.1 - 2014-08-19
+
+* Ensuring that the StreamAdapter does not always add a Content-Type header
+* Adding automated github releases with a phar and zip
+
+## 4.2.0 - 2014-08-17
+
+* Now merging in default options using a case-insensitive comparison.
+ Closes https://github.com/guzzle/guzzle/issues/767
+* Added the ability to automatically decode `Content-Encoding` response bodies
+ using the `decode_content` request option. This is set to `true` by default
+ to decode the response body if it comes over the wire with a
+ `Content-Encoding`. Set this value to `false` to disable decoding the
+ response content, and pass a string to provide a request `Accept-Encoding`
+ header and turn on automatic response decoding. This feature now allows you
+ to pass an `Accept-Encoding` header in the headers of a request but still
+ disable automatic response decoding.
+ Closes https://github.com/guzzle/guzzle/issues/764
+* Added the ability to throw an exception immediately when transferring
+ requests in parallel. Closes https://github.com/guzzle/guzzle/issues/760
+* Updating guzzlehttp/streams dependency to ~2.1
+* No longer utilizing the now deprecated namespaced methods from the stream
+ package.
+
+## 4.1.8 - 2014-08-14
+
+* Fixed an issue in the CurlFactory that caused setting the `stream=false`
+ request option to throw an exception.
+ See: https://github.com/guzzle/guzzle/issues/769
+* TransactionIterator now calls rewind on the inner iterator.
+ See: https://github.com/guzzle/guzzle/pull/765
+* You can now set the `Content-Type` header to `multipart/form-data`
+ when creating POST requests to force multipart bodies.
+ See https://github.com/guzzle/guzzle/issues/768
+
+## 4.1.7 - 2014-08-07
+
+* Fixed an error in the HistoryPlugin that caused the same request and response
+ to be logged multiple times when an HTTP protocol error occurs.
+* Ensuring that cURL does not add a default Content-Type when no Content-Type
+ has been supplied by the user. This prevents the adapter layer from modifying
+ the request that is sent over the wire after any listeners may have already
+ put the request in a desired state (e.g., signed the request).
+* Throwing an exception when you attempt to send requests that have the
+ "stream" set to true in parallel using the MultiAdapter.
+* Only calling curl_multi_select when there are active cURL handles. This was
+ previously changed and caused performance problems on some systems due to PHP
+ always selecting until the maximum select timeout.
+* Fixed a bug where multipart/form-data POST fields were not correctly
+ aggregated (e.g., values with "&").
+
+## 4.1.6 - 2014-08-03
+
+* Added helper methods to make it easier to represent messages as strings,
+ including getting the start line and getting headers as a string.
+
+## 4.1.5 - 2014-08-02
+
+* Automatically retrying cURL "Connection died, retrying a fresh connect"
+ errors when possible.
+* cURL implementation cleanup
+* Allowing multiple event subscriber listeners to be registered per event by
+ passing an array of arrays of listener configuration.
+
+## 4.1.4 - 2014-07-22
+
+* Fixed a bug that caused multi-part POST requests with more than one field to
+ serialize incorrectly.
+* Paths can now be set to "0"
+* `ResponseInterface::xml` now accepts a `libxml_options` option and added a
+ missing default argument that was required when parsing XML response bodies.
+* A `save_to` stream is now created lazily, which means that files are not
+ created on disk unless a request succeeds.
+
+## 4.1.3 - 2014-07-15
+
+* Various fixes to multipart/form-data POST uploads
+* Wrapping function.php in an if-statement to ensure Guzzle can be used
+ globally and in a Composer install
+* Fixed an issue with generating and merging in events to an event array
+* POST headers are only applied before sending a request to allow you to change
+ the query aggregator used before uploading
+* Added much more robust query string parsing
+* Fixed various parsing and normalization issues with URLs
+* Fixing an issue where multi-valued headers were not being utilized correctly
+ in the StreamAdapter
+
+## 4.1.2 - 2014-06-18
+
+* Added support for sending payloads with GET requests
+
+## 4.1.1 - 2014-06-08
+
+* Fixed an issue related to using custom message factory options in subclasses
+* Fixed an issue with nested form fields in a multi-part POST
+* Fixed an issue with using the `json` request option for POST requests
+* Added `ToArrayInterface` to `GuzzleHttp\Cookie\CookieJar`
+
+## 4.1.0 - 2014-05-27
+
+* Added a `json` request option to easily serialize JSON payloads.
+* Added a `GuzzleHttp\json_decode()` wrapper to safely parse JSON.
+* Added `setPort()` and `getPort()` to `GuzzleHttp\Message\RequestInterface`.
+* Added the ability to provide an emitter to a client in the client constructor.
+* Added the ability to persist a cookie session using $_SESSION.
+* Added a trait that can be used to add event listeners to an iterator.
+* Removed request method constants from RequestInterface.
+* Fixed warning when invalid request start-lines are received.
+* Updated MessageFactory to work with custom request option methods.
+* Updated cacert bundle to latest build.
+
+4.0.2 (2014-04-16)
+------------------
+
+* Proxy requests using the StreamAdapter now properly use request_fulluri (#632)
+* Added the ability to set scalars as POST fields (#628)
+
+## 4.0.1 - 2014-04-04
+
+* The HTTP status code of a response is now set as the exception code of
+ RequestException objects.
+* 303 redirects will now correctly switch from POST to GET requests.
+* The default parallel adapter of a client now correctly uses the MultiAdapter.
+* HasDataTrait now initializes the internal data array as an empty array so
+ that the toArray() method always returns an array.
+
+## 4.0.0 - 2014-03-29
+
+* For more information on the 4.0 transition, see:
+ http://mtdowling.com/blog/2014/03/15/guzzle-4-rc/
+* For information on changes and upgrading, see:
+ https://github.com/guzzle/guzzle/blob/master/UPGRADING.md#3x-to-40
+* Added `GuzzleHttp\batch()` as a convenience function for sending requests in
+ parallel without needing to write asynchronous code.
+* Restructured how events are added to `GuzzleHttp\ClientInterface::sendAll()`.
+ You can now pass a callable or an array of associative arrays where each
+ associative array contains the "fn", "priority", and "once" keys.
+
+## 4.0.0.rc-2 - 2014-03-25
+
+* Removed `getConfig()` and `setConfig()` from clients to avoid confusion
+ around whether things like base_url, message_factory, etc. should be able to
+ be retrieved or modified.
+* Added `getDefaultOption()` and `setDefaultOption()` to ClientInterface
+* functions.php functions were renamed using snake_case to match PHP idioms
+* Added support for `HTTP_PROXY`, `HTTPS_PROXY`, and
+ `GUZZLE_CURL_SELECT_TIMEOUT` environment variables
+* Added the ability to specify custom `sendAll()` event priorities
+* Added the ability to specify custom stream context options to the stream
+ adapter.
+* Added a functions.php function for `get_path()` and `set_path()`
+* CurlAdapter and MultiAdapter now use a callable to generate curl resources
+* MockAdapter now properly reads a body and emits a `headers` event
+* Updated Url class to check if a scheme and host are set before adding ":"
+ and "//". This allows empty Url (e.g., "") to be serialized as "".
+* Parsing invalid XML no longer emits warnings
+* Curl classes now properly throw AdapterExceptions
+* Various performance optimizations
+* Streams are created with the faster `Stream\create()` function
+* Marked deprecation_proxy() as internal
+* Test server is now a collection of static methods on a class
+
+## 4.0.0-rc.1 - 2014-03-15
+
+* See https://github.com/guzzle/guzzle/blob/master/UPGRADING.md#3x-to-40
+
+## 3.8.1 - 2014-01-28
+
+* Bug: Always using GET requests when redirecting from a 303 response
+* Bug: CURLOPT_SSL_VERIFYHOST is now correctly set to false when setting `$certificateAuthority` to false in
+ `Guzzle\Http\ClientInterface::setSslVerification()`
+* Bug: RedirectPlugin now uses strict RFC 3986 compliance when combining a base URL with a relative URL
+* Bug: The body of a request can now be set to `"0"`
+* Sending PHP stream requests no longer forces `HTTP/1.0`
+* Adding more information to ExceptionCollection exceptions so that users have more context, including a stack trace of
+ each sub-exception
+* Updated the `$ref` attribute in service descriptions to merge over any existing parameters of a schema (rather than
+ clobbering everything).
+* Merging URLs will now use the query string object from the relative URL (thus allowing custom query aggregators)
+* Query strings are now parsed in a way that they do no convert empty keys with no value to have a dangling `=`.
+ For example `foo&bar=baz` is now correctly parsed and recognized as `foo&bar=baz` rather than `foo=&bar=baz`.
+* Now properly escaping the regular expression delimiter when matching Cookie domains.
+* Network access is now disabled when loading XML documents
+
+## 3.8.0 - 2013-12-05
+
+* Added the ability to define a POST name for a file
+* JSON response parsing now properly walks additionalProperties
+* cURL error code 18 is now retried automatically in the BackoffPlugin
+* Fixed a cURL error when URLs contain fragments
+* Fixed an issue in the BackoffPlugin retry event where it was trying to access all exceptions as if they were
+ CurlExceptions
+* CURLOPT_PROGRESS function fix for PHP 5.5 (69fcc1e)
+* Added the ability for Guzzle to work with older versions of cURL that do not support `CURLOPT_TIMEOUT_MS`
+* Fixed a bug that was encountered when parsing empty header parameters
+* UriTemplate now has a `setRegex()` method to match the docs
+* The `debug` request parameter now checks if it is truthy rather than if it exists
+* Setting the `debug` request parameter to true shows verbose cURL output instead of using the LogPlugin
+* Added the ability to combine URLs using strict RFC 3986 compliance
+* Command objects can now return the validation errors encountered by the command
+* Various fixes to cache revalidation (#437 and 29797e5)
+* Various fixes to the AsyncPlugin
+* Cleaned up build scripts
+
+## 3.7.4 - 2013-10-02
+
+* Bug fix: 0 is now an allowed value in a description parameter that has a default value (#430)
+* Bug fix: SchemaFormatter now returns an integer when formatting to a Unix timestamp
+ (see https://github.com/aws/aws-sdk-php/issues/147)
+* Bug fix: Cleaned up and fixed URL dot segment removal to properly resolve internal dots
+* Minimum PHP version is now properly specified as 5.3.3 (up from 5.3.2) (#420)
+* Updated the bundled cacert.pem (#419)
+* OauthPlugin now supports adding authentication to headers or query string (#425)
+
+## 3.7.3 - 2013-09-08
+
+* Added the ability to get the exception associated with a request/command when using `MultiTransferException` and
+ `CommandTransferException`.
+* Setting `additionalParameters` of a response to false is now honored when parsing responses with a service description
+* Schemas are only injected into response models when explicitly configured.
+* No longer guessing Content-Type based on the path of a request. Content-Type is now only guessed based on the path of
+ an EntityBody.
+* Bug fix: ChunkedIterator can now properly chunk a \Traversable as well as an \Iterator.
+* Bug fix: FilterIterator now relies on `\Iterator` instead of `\Traversable`.
+* Bug fix: Gracefully handling malformed responses in RequestMediator::writeResponseBody()
+* Bug fix: Replaced call to canCache with canCacheRequest in the CallbackCanCacheStrategy of the CachePlugin
+* Bug fix: Visiting XML attributes first before visiting XML children when serializing requests
+* Bug fix: Properly parsing headers that contain commas contained in quotes
+* Bug fix: mimetype guessing based on a filename is now case-insensitive
+
+## 3.7.2 - 2013-08-02
+
+* Bug fix: Properly URL encoding paths when using the PHP-only version of the UriTemplate expander
+ See https://github.com/guzzle/guzzle/issues/371
+* Bug fix: Cookie domains are now matched correctly according to RFC 6265
+ See https://github.com/guzzle/guzzle/issues/377
+* Bug fix: GET parameters are now used when calculating an OAuth signature
+* Bug fix: Fixed an issue with cache revalidation where the If-None-Match header was being double quoted
+* `Guzzle\Common\AbstractHasDispatcher::dispatch()` now returns the event that was dispatched
+* `Guzzle\Http\QueryString::factory()` now guesses the most appropriate query aggregator to used based on the input.
+ See https://github.com/guzzle/guzzle/issues/379
+* Added a way to add custom domain objects to service description parsing using the `operation.parse_class` event. See
+ https://github.com/guzzle/guzzle/pull/380
+* cURL multi cleanup and optimizations
+
+## 3.7.1 - 2013-07-05
+
+* Bug fix: Setting default options on a client now works
+* Bug fix: Setting options on HEAD requests now works. See #352
+* Bug fix: Moving stream factory before send event to before building the stream. See #353
+* Bug fix: Cookies no longer match on IP addresses per RFC 6265
+* Bug fix: Correctly parsing header parameters that are in `<>` and quotes
+* Added `cert` and `ssl_key` as request options
+* `Host` header can now diverge from the host part of a URL if the header is set manually
+* `Guzzle\Service\Command\LocationVisitor\Request\XmlVisitor` was rewritten to change from using SimpleXML to XMLWriter
+* OAuth parameters are only added via the plugin if they aren't already set
+* Exceptions are now thrown when a URL cannot be parsed
+* Returning `false` if `Guzzle\Http\EntityBody::getContentMd5()` fails
+* Not setting a `Content-MD5` on a command if calculating the Content-MD5 fails via the CommandContentMd5Plugin
+
+## 3.7.0 - 2013-06-10
+
+* See UPGRADING.md for more information on how to upgrade.
+* Requests now support the ability to specify an array of $options when creating a request to more easily modify a
+ request. You can pass a 'request.options' configuration setting to a client to apply default request options to
+ every request created by a client (e.g. default query string variables, headers, curl options, etc.).
+* Added a static facade class that allows you to use Guzzle with static methods and mount the class to `\Guzzle`.
+ See `Guzzle\Http\StaticClient::mount`.
+* Added `command.request_options` to `Guzzle\Service\Command\AbstractCommand` to pass request options to requests
+ created by a command (e.g. custom headers, query string variables, timeout settings, etc.).
+* Stream size in `Guzzle\Stream\PhpStreamRequestFactory` will now be set if Content-Length is returned in the
+ headers of a response
+* Added `Guzzle\Common\Collection::setPath($path, $value)` to set a value into an array using a nested key
+ (e.g. `$collection->setPath('foo/baz/bar', 'test'); echo $collection['foo']['bar']['bar'];`)
+* ServiceBuilders now support storing and retrieving arbitrary data
+* CachePlugin can now purge all resources for a given URI
+* CachePlugin can automatically purge matching cached items when a non-idempotent request is sent to a resource
+* CachePlugin now uses the Vary header to determine if a resource is a cache hit
+* `Guzzle\Http\Message\Response` now implements `\Serializable`
+* Added `Guzzle\Cache\CacheAdapterFactory::fromCache()` to more easily create cache adapters
+* `Guzzle\Service\ClientInterface::execute()` now accepts an array, single command, or Traversable
+* Fixed a bug in `Guzzle\Http\Message\Header\Link::addLink()`
+* Better handling of calculating the size of a stream in `Guzzle\Stream\Stream` using fstat() and caching the size
+* `Guzzle\Common\Exception\ExceptionCollection` now creates a more readable exception message
+* Fixing BC break: Added back the MonologLogAdapter implementation rather than extending from PsrLog so that older
+ Symfony users can still use the old version of Monolog.
+* Fixing BC break: Added the implementation back in for `Guzzle\Http\Message\AbstractMessage::getTokenizedHeader()`.
+ Now triggering an E_USER_DEPRECATED warning when used. Use `$message->getHeader()->parseParams()`.
+* Several performance improvements to `Guzzle\Common\Collection`
+* Added an `$options` argument to the end of the following methods of `Guzzle\Http\ClientInterface`:
+ createRequest, head, delete, put, patch, post, options, prepareRequest
+* Added an `$options` argument to the end of `Guzzle\Http\Message\Request\RequestFactoryInterface::createRequest()`
+* Added an `applyOptions()` method to `Guzzle\Http\Message\Request\RequestFactoryInterface`
+* Changed `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $body = null)` to
+ `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $options = array())`. You can still pass in a
+ resource, string, or EntityBody into the $options parameter to specify the download location of the response.
+* Changed `Guzzle\Common\Collection::__construct($data)` to no longer accepts a null value for `$data` but a
+ default `array()`
+* Added `Guzzle\Stream\StreamInterface::isRepeatable`
+* Removed `Guzzle\Http\ClientInterface::setDefaultHeaders(). Use
+ $client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`. or
+ $client->getConfig()->setPath('request.options/headers', array('header_name' => 'value'))`.
+* Removed `Guzzle\Http\ClientInterface::getDefaultHeaders(). Use $client->getConfig()->getPath('request.options/headers')`.
+* Removed `Guzzle\Http\ClientInterface::expandTemplate()`
+* Removed `Guzzle\Http\ClientInterface::setRequestFactory()`
+* Removed `Guzzle\Http\ClientInterface::getCurlMulti()`
+* Removed `Guzzle\Http\Message\RequestInterface::canCache`
+* Removed `Guzzle\Http\Message\RequestInterface::setIsRedirect`
+* Removed `Guzzle\Http\Message\RequestInterface::isRedirect`
+* Made `Guzzle\Http\Client::expandTemplate` and `getUriTemplate` protected methods.
+* You can now enable E_USER_DEPRECATED warnings to see if you are using a deprecated method by setting
+ `Guzzle\Common\Version::$emitWarnings` to true.
+* Marked `Guzzle\Http\Message\Request::isResponseBodyRepeatable()` as deprecated. Use
+ `$request->getResponseBody()->isRepeatable()` instead.
+* Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use
+ `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead.
+* Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use
+ `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead.
+* Marked `Guzzle\Http\Message\Request::setIsRedirect()` as deprecated. Use the HistoryPlugin instead.
+* Marked `Guzzle\Http\Message\Request::isRedirect()` as deprecated. Use the HistoryPlugin instead.
+* Marked `Guzzle\Cache\CacheAdapterFactory::factory()` as deprecated
+* Marked 'command.headers', 'command.response_body' and 'command.on_complete' as deprecated for AbstractCommand.
+ These will work through Guzzle 4.0
+* Marked 'request.params' for `Guzzle\Http\Client` as deprecated. Use [request.options][params].
+* Marked `Guzzle\Service\Client::enableMagicMethods()` as deprecated. Magic methods can no longer be disabled on a Guzzle\Service\Client.
+* Marked `Guzzle\Service\Client::getDefaultHeaders()` as deprecated. Use $client->getConfig()->getPath('request.options/headers')`.
+* Marked `Guzzle\Service\Client::setDefaultHeaders()` as deprecated. Use $client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`.
+* Marked `Guzzle\Parser\Url\UrlParser` as deprecated. Just use PHP's `parse_url()` and percent encode your UTF-8.
+* Marked `Guzzle\Common\Collection::inject()` as deprecated.
+* Marked `Guzzle\Plugin\CurlAuth\CurlAuthPlugin` as deprecated. Use `$client->getConfig()->setPath('request.options/auth', array('user', 'pass', 'Basic|Digest');`
+* CacheKeyProviderInterface and DefaultCacheKeyProvider are no longer used. All of this logic is handled in a
+ CacheStorageInterface. These two objects and interface will be removed in a future version.
+* Always setting X-cache headers on cached responses
+* Default cache TTLs are now handled by the CacheStorageInterface of a CachePlugin
+* `CacheStorageInterface::cache($key, Response $response, $ttl = null)` has changed to `cache(RequestInterface
+ $request, Response $response);`
+* `CacheStorageInterface::fetch($key)` has changed to `fetch(RequestInterface $request);`
+* `CacheStorageInterface::delete($key)` has changed to `delete(RequestInterface $request);`
+* Added `CacheStorageInterface::purge($url)`
+* `DefaultRevalidation::__construct(CacheKeyProviderInterface $cacheKey, CacheStorageInterface $cache, CachePlugin
+ $plugin)` has changed to `DefaultRevalidation::__construct(CacheStorageInterface $cache,
+ CanCacheStrategyInterface $canCache = null)`
+* Added `RevalidationInterface::shouldRevalidate(RequestInterface $request, Response $response)`
+
+## 3.6.0 - 2013-05-29
+
+* ServiceDescription now implements ToArrayInterface
+* Added command.hidden_params to blacklist certain headers from being treated as additionalParameters
+* Guzzle can now correctly parse incomplete URLs
+* Mixed casing of headers are now forced to be a single consistent casing across all values for that header.
+* Messages internally use a HeaderCollection object to delegate handling case-insensitive header resolution
+* Removed the whole changedHeader() function system of messages because all header changes now go through addHeader().
+* Specific header implementations can be created for complex headers. When a message creates a header, it uses a
+ HeaderFactory which can map specific headers to specific header classes. There is now a Link header and
+ CacheControl header implementation.
+* Removed from interface: Guzzle\Http\ClientInterface::setUriTemplate
+* Removed from interface: Guzzle\Http\ClientInterface::setCurlMulti()
+* Removed Guzzle\Http\Message\Request::receivedRequestHeader() and implemented this functionality in
+ Guzzle\Http\Curl\RequestMediator
+* Removed the optional $asString parameter from MessageInterface::getHeader(). Just cast the header to a string.
+* Removed the optional $tryChunkedTransfer option from Guzzle\Http\Message\EntityEnclosingRequestInterface
+* Removed the $asObjects argument from Guzzle\Http\Message\MessageInterface::getHeaders()
+* Removed Guzzle\Parser\ParserRegister::get(). Use getParser()
+* Removed Guzzle\Parser\ParserRegister::set(). Use registerParser().
+* All response header helper functions return a string rather than mixing Header objects and strings inconsistently
+* Removed cURL blacklist support. This is no longer necessary now that Expect, Accept, etc. are managed by Guzzle
+ directly via interfaces
+* Removed the injecting of a request object onto a response object. The methods to get and set a request still exist
+ but are a no-op until removed.
+* Most classes that used to require a `Guzzle\Service\Command\CommandInterface` typehint now request a
+ `Guzzle\Service\Command\ArrayCommandInterface`.
+* Added `Guzzle\Http\Message\RequestInterface::startResponse()` to the RequestInterface to handle injecting a response
+ on a request while the request is still being transferred
+* The ability to case-insensitively search for header values
+* Guzzle\Http\Message\Header::hasExactHeader
+* Guzzle\Http\Message\Header::raw. Use getAll()
+* Deprecated cache control specific methods on Guzzle\Http\Message\AbstractMessage. Use the CacheControl header object
+ instead.
+* `Guzzle\Service\Command\CommandInterface` now extends from ToArrayInterface and ArrayAccess
+* Added the ability to cast Model objects to a string to view debug information.
+
+## 3.5.0 - 2013-05-13
+
+* Bug: Fixed a regression so that request responses are parsed only once per oncomplete event rather than multiple times
+* Bug: Better cleanup of one-time events across the board (when an event is meant to fire once, it will now remove
+ itself from the EventDispatcher)
+* Bug: `Guzzle\Log\MessageFormatter` now properly writes "total_time" and "connect_time" values
+* Bug: Cloning an EntityEnclosingRequest now clones the EntityBody too
+* Bug: Fixed an undefined index error when parsing nested JSON responses with a sentAs parameter that reference a
+ non-existent key
+* Bug: All __call() method arguments are now required (helps with mocking frameworks)
+* Deprecating Response::getRequest() and now using a shallow clone of a request object to remove a circular reference
+ to help with refcount based garbage collection of resources created by sending a request
+* Deprecating ZF1 cache and log adapters. These will be removed in the next major version.
+* Deprecating `Response::getPreviousResponse()` (method signature still exists, but it'sdeprecated). Use the
+ HistoryPlugin for a history.
+* Added a `responseBody` alias for the `response_body` location
+* Refactored internals to no longer rely on Response::getRequest()
+* HistoryPlugin can now be cast to a string
+* HistoryPlugin now logs transactions rather than requests and responses to more accurately keep track of the requests
+ and responses that are sent over the wire
+* Added `getEffectiveUrl()` and `getRedirectCount()` to Response objects
+
+## 3.4.3 - 2013-04-30
+
+* Bug fix: Fixing bug introduced in 3.4.2 where redirect responses are duplicated on the final redirected response
+* Added a check to re-extract the temp cacert bundle from the phar before sending each request
+
+## 3.4.2 - 2013-04-29
+
+* Bug fix: Stream objects now work correctly with "a" and "a+" modes
+* Bug fix: Removing `Transfer-Encoding: chunked` header when a Content-Length is present
+* Bug fix: AsyncPlugin no longer forces HEAD requests
+* Bug fix: DateTime timezones are now properly handled when using the service description schema formatter
+* Bug fix: CachePlugin now properly handles stale-if-error directives when a request to the origin server fails
+* Setting a response on a request will write to the custom request body from the response body if one is specified
+* LogPlugin now writes to php://output when STDERR is undefined
+* Added the ability to set multiple POST files for the same key in a single call
+* application/x-www-form-urlencoded POSTs now use the utf-8 charset by default
+* Added the ability to queue CurlExceptions to the MockPlugin
+* Cleaned up how manual responses are queued on requests (removed "queued_response" and now using request.before_send)
+* Configuration loading now allows remote files
+
+## 3.4.1 - 2013-04-16
+
+* Large refactoring to how CurlMulti handles work. There is now a proxy that sits in front of a pool of CurlMulti
+ handles. This greatly simplifies the implementation, fixes a couple bugs, and provides a small performance boost.
+* Exceptions are now properly grouped when sending requests in parallel
+* Redirects are now properly aggregated when a multi transaction fails
+* Redirects now set the response on the original object even in the event of a failure
+* Bug fix: Model names are now properly set even when using $refs
+* Added support for PHP 5.5's CurlFile to prevent warnings with the deprecated @ syntax
+* Added support for oauth_callback in OAuth signatures
+* Added support for oauth_verifier in OAuth signatures
+* Added support to attempt to retrieve a command first literally, then ucfirst, the with inflection
+
+## 3.4.0 - 2013-04-11
+
+* Bug fix: URLs are now resolved correctly based on http://tools.ietf.org/html/rfc3986#section-5.2. #289
+* Bug fix: Absolute URLs with a path in a service description will now properly override the base URL. #289
+* Bug fix: Parsing a query string with a single PHP array value will now result in an array. #263
+* Bug fix: Better normalization of the User-Agent header to prevent duplicate headers. #264.
+* Bug fix: Added `number` type to service descriptions.
+* Bug fix: empty parameters are removed from an OAuth signature
+* Bug fix: Revalidating a cache entry prefers the Last-Modified over the Date header
+* Bug fix: Fixed "array to string" error when validating a union of types in a service description
+* Bug fix: Removed code that attempted to determine the size of a stream when data is written to the stream
+* Bug fix: Not including an `oauth_token` if the value is null in the OauthPlugin.
+* Bug fix: Now correctly aggregating successful requests and failed requests in CurlMulti when a redirect occurs.
+* The new default CURLOPT_TIMEOUT setting has been increased to 150 seconds so that Guzzle works on poor connections.
+* Added a feature to EntityEnclosingRequest::setBody() that will automatically set the Content-Type of the request if
+ the Content-Type can be determined based on the entity body or the path of the request.
+* Added the ability to overwrite configuration settings in a client when grabbing a throwaway client from a builder.
+* Added support for a PSR-3 LogAdapter.
+* Added a `command.after_prepare` event
+* Added `oauth_callback` parameter to the OauthPlugin
+* Added the ability to create a custom stream class when using a stream factory
+* Added a CachingEntityBody decorator
+* Added support for `additionalParameters` in service descriptions to define how custom parameters are serialized.
+* The bundled SSL certificate is now provided in the phar file and extracted when running Guzzle from a phar.
+* You can now send any EntityEnclosingRequest with POST fields or POST files and cURL will handle creating bodies
+* POST requests using a custom entity body are now treated exactly like PUT requests but with a custom cURL method. This
+ means that the redirect behavior of POST requests with custom bodies will not be the same as POST requests that use
+ POST fields or files (the latter is only used when emulating a form POST in the browser).
+* Lots of cleanup to CurlHandle::factory and RequestFactory::createRequest
+
+## 3.3.1 - 2013-03-10
+
+* Added the ability to create PHP streaming responses from HTTP requests
+* Bug fix: Running any filters when parsing response headers with service descriptions
+* Bug fix: OauthPlugin fixes to allow for multi-dimensional array signing, and sorting parameters before signing
+* Bug fix: Removed the adding of default empty arrays and false Booleans to responses in order to be consistent across
+ response location visitors.
+* Bug fix: Removed the possibility of creating configuration files with circular dependencies
+* RequestFactory::create() now uses the key of a POST file when setting the POST file name
+* Added xmlAllowEmpty to serialize an XML body even if no XML specific parameters are set
+
+## 3.3.0 - 2013-03-03
+
+* A large number of performance optimizations have been made
+* Bug fix: Added 'wb' as a valid write mode for streams
+* Bug fix: `Guzzle\Http\Message\Response::json()` now allows scalar values to be returned
+* Bug fix: Fixed bug in `Guzzle\Http\Message\Response` where wrapping quotes were stripped from `getEtag()`
+* BC: Removed `Guzzle\Http\Utils` class
+* BC: Setting a service description on a client will no longer modify the client's command factories.
+* BC: Emitting IO events from a RequestMediator is now a parameter that must be set in a request's curl options using
+ the 'emit_io' key. This was previously set under a request's parameters using 'curl.emit_io'
+* BC: `Guzzle\Stream\Stream::getWrapper()` and `Guzzle\Stream\Stream::getSteamType()` are no longer converted to
+ lowercase
+* Operation parameter objects are now lazy loaded internally
+* Added ErrorResponsePlugin that can throw errors for responses defined in service description operations' errorResponses
+* Added support for instantiating responseType=class responseClass classes. Classes must implement
+ `Guzzle\Service\Command\ResponseClassInterface`
+* Added support for additionalProperties for top-level parameters in responseType=model responseClasses. These
+ additional properties also support locations and can be used to parse JSON responses where the outermost part of the
+ JSON is an array
+* Added support for nested renaming of JSON models (rename sentAs to name)
+* CachePlugin
+ * Added support for stale-if-error so that the CachePlugin can now serve stale content from the cache on error
+ * Debug headers can now added to cached response in the CachePlugin
+
+## 3.2.0 - 2013-02-14
+
+* CurlMulti is no longer reused globally. A new multi object is created per-client. This helps to isolate clients.
+* URLs with no path no longer contain a "/" by default
+* Guzzle\Http\QueryString does no longer manages the leading "?". This is now handled in Guzzle\Http\Url.
+* BadResponseException no longer includes the full request and response message
+* Adding setData() to Guzzle\Service\Description\ServiceDescriptionInterface
+* Adding getResponseBody() to Guzzle\Http\Message\RequestInterface
+* Various updates to classes to use ServiceDescriptionInterface type hints rather than ServiceDescription
+* Header values can now be normalized into distinct values when multiple headers are combined with a comma separated list
+* xmlEncoding can now be customized for the XML declaration of a XML service description operation
+* Guzzle\Http\QueryString now uses Guzzle\Http\QueryAggregator\QueryAggregatorInterface objects to add custom value
+ aggregation and no longer uses callbacks
+* The URL encoding implementation of Guzzle\Http\QueryString can now be customized
+* Bug fix: Filters were not always invoked for array service description parameters
+* Bug fix: Redirects now use a target response body rather than a temporary response body
+* Bug fix: The default exponential backoff BackoffPlugin was not giving when the request threshold was exceeded
+* Bug fix: Guzzle now takes the first found value when grabbing Cache-Control directives
+
+## 3.1.2 - 2013-01-27
+
+* Refactored how operation responses are parsed. Visitors now include a before() method responsible for parsing the
+ response body. For example, the XmlVisitor now parses the XML response into an array in the before() method.
+* Fixed an issue where cURL would not automatically decompress responses when the Accept-Encoding header was sent
+* CURLOPT_SSL_VERIFYHOST is never set to 1 because it is deprecated (see 5e0ff2ef20f839e19d1eeb298f90ba3598784444)
+* Fixed a bug where redirect responses were not chained correctly using getPreviousResponse()
+* Setting default headers on a client after setting the user-agent will not erase the user-agent setting
+
+## 3.1.1 - 2013-01-20
+
+* Adding wildcard support to Guzzle\Common\Collection::getPath()
+* Adding alias support to ServiceBuilder configs
+* Adding Guzzle\Service\Resource\CompositeResourceIteratorFactory and cleaning up factory interface
+
+## 3.1.0 - 2013-01-12
+
+* BC: CurlException now extends from RequestException rather than BadResponseException
+* BC: Renamed Guzzle\Plugin\Cache\CanCacheStrategyInterface::canCache() to canCacheRequest() and added CanCacheResponse()
+* Added getData to ServiceDescriptionInterface
+* Added context array to RequestInterface::setState()
+* Bug: Removing hard dependency on the BackoffPlugin from Guzzle\Http
+* Bug: Adding required content-type when JSON request visitor adds JSON to a command
+* Bug: Fixing the serialization of a service description with custom data
+* Made it easier to deal with exceptions thrown when transferring commands or requests in parallel by providing
+ an array of successful and failed responses
+* Moved getPath from Guzzle\Service\Resource\Model to Guzzle\Common\Collection
+* Added Guzzle\Http\IoEmittingEntityBody
+* Moved command filtration from validators to location visitors
+* Added `extends` attributes to service description parameters
+* Added getModels to ServiceDescriptionInterface
+
+## 3.0.7 - 2012-12-19
+
+* Fixing phar detection when forcing a cacert to system if null or true
+* Allowing filename to be passed to `Guzzle\Http\Message\Request::setResponseBody()`
+* Cleaning up `Guzzle\Common\Collection::inject` method
+* Adding a response_body location to service descriptions
+
+## 3.0.6 - 2012-12-09
+
+* CurlMulti performance improvements
+* Adding setErrorResponses() to Operation
+* composer.json tweaks
+
+## 3.0.5 - 2012-11-18
+
+* Bug: Fixing an infinite recursion bug caused from revalidating with the CachePlugin
+* Bug: Response body can now be a string containing "0"
+* Bug: Using Guzzle inside of a phar uses system by default but now allows for a custom cacert
+* Bug: QueryString::fromString now properly parses query string parameters that contain equal signs
+* Added support for XML attributes in service description responses
+* DefaultRequestSerializer now supports array URI parameter values for URI template expansion
+* Added better mimetype guessing to requests and post files
+
+## 3.0.4 - 2012-11-11
+
+* Bug: Fixed a bug when adding multiple cookies to a request to use the correct glue value
+* Bug: Cookies can now be added that have a name, domain, or value set to "0"
+* Bug: Using the system cacert bundle when using the Phar
+* Added json and xml methods to Response to make it easier to parse JSON and XML response data into data structures
+* Enhanced cookie jar de-duplication
+* Added the ability to enable strict cookie jars that throw exceptions when invalid cookies are added
+* Added setStream to StreamInterface to actually make it possible to implement custom rewind behavior for entity bodies
+* Added the ability to create any sort of hash for a stream rather than just an MD5 hash
+
+## 3.0.3 - 2012-11-04
+
+* Implementing redirects in PHP rather than cURL
+* Added PECL URI template extension and using as default parser if available
+* Bug: Fixed Content-Length parsing of Response factory
+* Adding rewind() method to entity bodies and streams. Allows for custom rewinding of non-repeatable streams.
+* Adding ToArrayInterface throughout library
+* Fixing OauthPlugin to create unique nonce values per request
+
+## 3.0.2 - 2012-10-25
+
+* Magic methods are enabled by default on clients
+* Magic methods return the result of a command
+* Service clients no longer require a base_url option in the factory
+* Bug: Fixed an issue with URI templates where null template variables were being expanded
+
+## 3.0.1 - 2012-10-22
+
+* Models can now be used like regular collection objects by calling filter, map, etc.
+* Models no longer require a Parameter structure or initial data in the constructor
+* Added a custom AppendIterator to get around a PHP bug with the `\AppendIterator`
+
+## 3.0.0 - 2012-10-15
+
+* Rewrote service description format to be based on Swagger
+ * Now based on JSON schema
+ * Added nested input structures and nested response models
+ * Support for JSON and XML input and output models
+ * Renamed `commands` to `operations`
+ * Removed dot class notation
+ * Removed custom types
+* Broke the project into smaller top-level namespaces to be more component friendly
+* Removed support for XML configs and descriptions. Use arrays or JSON files.
+* Removed the Validation component and Inspector
+* Moved all cookie code to Guzzle\Plugin\Cookie
+* Magic methods on a Guzzle\Service\Client now return the command un-executed.
+* Calling getResult() or getResponse() on a command will lazily execute the command if needed.
+* Now shipping with cURL's CA certs and using it by default
+* Added previousResponse() method to response objects
+* No longer sending Accept and Accept-Encoding headers on every request
+* Only sending an Expect header by default when a payload is greater than 1MB
+* Added/moved client options:
+ * curl.blacklist to curl.option.blacklist
+ * Added ssl.certificate_authority
+* Added a Guzzle\Iterator component
+* Moved plugins from Guzzle\Http\Plugin to Guzzle\Plugin
+* Added a more robust backoff retry strategy (replaced the ExponentialBackoffPlugin)
+* Added a more robust caching plugin
+* Added setBody to response objects
+* Updating LogPlugin to use a more flexible MessageFormatter
+* Added a completely revamped build process
+* Cleaning up Collection class and removing default values from the get method
+* Fixed ZF2 cache adapters
+
+## 2.8.8 - 2012-10-15
+
+* Bug: Fixed a cookie issue that caused dot prefixed domains to not match where popular browsers did
+
+## 2.8.7 - 2012-09-30
+
+* Bug: Fixed config file aliases for JSON includes
+* Bug: Fixed cookie bug on a request object by using CookieParser to parse cookies on requests
+* Bug: Removing the path to a file when sending a Content-Disposition header on a POST upload
+* Bug: Hardening request and response parsing to account for missing parts
+* Bug: Fixed PEAR packaging
+* Bug: Fixed Request::getInfo
+* Bug: Fixed cases where CURLM_CALL_MULTI_PERFORM return codes were causing curl transactions to fail
+* Adding the ability for the namespace Iterator factory to look in multiple directories
+* Added more getters/setters/removers from service descriptions
+* Added the ability to remove POST fields from OAuth signatures
+* OAuth plugin now supports 2-legged OAuth
+
+## 2.8.6 - 2012-09-05
+
+* Added the ability to modify and build service descriptions
+* Added the use of visitors to apply parameters to locations in service descriptions using the dynamic command
+* Added a `json` parameter location
+* Now allowing dot notation for classes in the CacheAdapterFactory
+* Using the union of two arrays rather than an array_merge when extending service builder services and service params
+* Ensuring that a service is a string before doing strpos() checks on it when substituting services for references
+ in service builder config files.
+* Services defined in two different config files that include one another will by default replace the previously
+ defined service, but you can now create services that extend themselves and merge their settings over the previous
+* The JsonLoader now supports aliasing filenames with different filenames. This allows you to alias something like
+ '_default' with a default JSON configuration file.
+
+## 2.8.5 - 2012-08-29
+
+* Bug: Suppressed empty arrays from URI templates
+* Bug: Added the missing $options argument from ServiceDescription::factory to enable caching
+* Added support for HTTP responses that do not contain a reason phrase in the start-line
+* AbstractCommand commands are now invokable
+* Added a way to get the data used when signing an Oauth request before a request is sent
+
+## 2.8.4 - 2012-08-15
+
+* Bug: Custom delay time calculations are no longer ignored in the ExponentialBackoffPlugin
+* Added the ability to transfer entity bodies as a string rather than streamed. This gets around curl error 65. Set `body_as_string` in a request's curl options to enable.
+* Added a StreamInterface, EntityBodyInterface, and added ftell() to Guzzle\Common\Stream
+* Added an AbstractEntityBodyDecorator and a ReadLimitEntityBody decorator to transfer only a subset of a decorated stream
+* Stream and EntityBody objects will now return the file position to the previous position after a read required operation (e.g. getContentMd5())
+* Added additional response status codes
+* Removed SSL information from the default User-Agent header
+* DELETE requests can now send an entity body
+* Added an EventDispatcher to the ExponentialBackoffPlugin and added an ExponentialBackoffLogger to log backoff retries
+* Added the ability of the MockPlugin to consume mocked request bodies
+* LogPlugin now exposes request and response objects in the extras array
+
+## 2.8.3 - 2012-07-30
+
+* Bug: Fixed a case where empty POST requests were sent as GET requests
+* Bug: Fixed a bug in ExponentialBackoffPlugin that caused fatal errors when retrying an EntityEnclosingRequest that does not have a body
+* Bug: Setting the response body of a request to null after completing a request, not when setting the state of a request to new
+* Added multiple inheritance to service description commands
+* Added an ApiCommandInterface and added `getParamNames()` and `hasParam()`
+* Removed the default 2mb size cutoff from the Md5ValidatorPlugin so that it now defaults to validating everything
+* Changed CurlMulti::perform to pass a smaller timeout to CurlMulti::executeHandles
+
+## 2.8.2 - 2012-07-24
+
+* Bug: Query string values set to 0 are no longer dropped from the query string
+* Bug: A Collection object is no longer created each time a call is made to `Guzzle\Service\Command\AbstractCommand::getRequestHeaders()`
+* Bug: `+` is now treated as an encoded space when parsing query strings
+* QueryString and Collection performance improvements
+* Allowing dot notation for class paths in filters attribute of a service descriptions
+
+## 2.8.1 - 2012-07-16
+
+* Loosening Event Dispatcher dependency
+* POST redirects can now be customized using CURLOPT_POSTREDIR
+
+## 2.8.0 - 2012-07-15
+
+* BC: Guzzle\Http\Query
+ * Query strings with empty variables will always show an equal sign unless the variable is set to QueryString::BLANK (e.g. ?acl= vs ?acl)
+ * Changed isEncodingValues() and isEncodingFields() to isUrlEncoding()
+ * Changed setEncodeValues(bool) and setEncodeFields(bool) to useUrlEncoding(bool)
+ * Changed the aggregation functions of QueryString to be static methods
+ * Can now use fromString() with querystrings that have a leading ?
+* cURL configuration values can be specified in service descriptions using `curl.` prefixed parameters
+* Content-Length is set to 0 before emitting the request.before_send event when sending an empty request body
+* Cookies are no longer URL decoded by default
+* Bug: URI template variables set to null are no longer expanded
+
+## 2.7.2 - 2012-07-02
+
+* BC: Moving things to get ready for subtree splits. Moving Inflection into Common. Moving Guzzle\Http\Parser to Guzzle\Parser.
+* BC: Removing Guzzle\Common\Batch\Batch::count() and replacing it with isEmpty()
+* CachePlugin now allows for a custom request parameter function to check if a request can be cached
+* Bug fix: CachePlugin now only caches GET and HEAD requests by default
+* Bug fix: Using header glue when transferring headers over the wire
+* Allowing deeply nested arrays for composite variables in URI templates
+* Batch divisors can now return iterators or arrays
+
+## 2.7.1 - 2012-06-26
+
+* Minor patch to update version number in UA string
+* Updating build process
+
+## 2.7.0 - 2012-06-25
+
+* BC: Inflection classes moved to Guzzle\Inflection. No longer static methods. Can now inject custom inflectors into classes.
+* BC: Removed magic setX methods from commands
+* BC: Magic methods mapped to service description commands are now inflected in the command factory rather than the client __call() method
+* Verbose cURL options are no longer enabled by default. Set curl.debug to true on a client to enable.
+* Bug: Now allowing colons in a response start-line (e.g. HTTP/1.1 503 Service Unavailable: Back-end server is at capacity)
+* Guzzle\Service\Resource\ResourceIteratorApplyBatched now internally uses the Guzzle\Common\Batch namespace
+* Added Guzzle\Service\Plugin namespace and a PluginCollectionPlugin
+* Added the ability to set POST fields and files in a service description
+* Guzzle\Http\EntityBody::factory() now accepts objects with a __toString() method
+* Adding a command.before_prepare event to clients
+* Added BatchClosureTransfer and BatchClosureDivisor
+* BatchTransferException now includes references to the batch divisor and transfer strategies
+* Fixed some tests so that they pass more reliably
+* Added Guzzle\Common\Log\ArrayLogAdapter
+
+## 2.6.6 - 2012-06-10
+
+* BC: Removing Guzzle\Http\Plugin\BatchQueuePlugin
+* BC: Removing Guzzle\Service\Command\CommandSet
+* Adding generic batching system (replaces the batch queue plugin and command set)
+* Updating ZF cache and log adapters and now using ZF's composer repository
+* Bug: Setting the name of each ApiParam when creating through an ApiCommand
+* Adding result_type, result_doc, deprecated, and doc_url to service descriptions
+* Bug: Changed the default cookie header casing back to 'Cookie'
+
+## 2.6.5 - 2012-06-03
+
+* BC: Renaming Guzzle\Http\Message\RequestInterface::getResourceUri() to getResource()
+* BC: Removing unused AUTH_BASIC and AUTH_DIGEST constants from
+* BC: Guzzle\Http\Cookie is now used to manage Set-Cookie data, not Cookie data
+* BC: Renaming methods in the CookieJarInterface
+* Moving almost all cookie logic out of the CookiePlugin and into the Cookie or CookieJar implementations
+* Making the default glue for HTTP headers ';' instead of ','
+* Adding a removeValue to Guzzle\Http\Message\Header
+* Adding getCookies() to request interface.
+* Making it easier to add event subscribers to HasDispatcherInterface classes. Can now directly call addSubscriber()
+
+## 2.6.4 - 2012-05-30
+
+* BC: Cleaning up how POST files are stored in EntityEnclosingRequest objects. Adding PostFile class.
+* BC: Moving ApiCommand specific functionality from the Inspector and on to the ApiCommand
+* Bug: Fixing magic method command calls on clients
+* Bug: Email constraint only validates strings
+* Bug: Aggregate POST fields when POST files are present in curl handle
+* Bug: Fixing default User-Agent header
+* Bug: Only appending or prepending parameters in commands if they are specified
+* Bug: Not requiring response reason phrases or status codes to match a predefined list of codes
+* Allowing the use of dot notation for class namespaces when using instance_of constraint
+* Added any_match validation constraint
+* Added an AsyncPlugin
+* Passing request object to the calculateWait method of the ExponentialBackoffPlugin
+* Allowing the result of a command object to be changed
+* Parsing location and type sub values when instantiating a service description rather than over and over at runtime
+
+## 2.6.3 - 2012-05-23
+
+* [BC] Guzzle\Common\FromConfigInterface no longer requires any config options.
+* [BC] Refactoring how POST files are stored on an EntityEnclosingRequest. They are now separate from POST fields.
+* You can now use an array of data when creating PUT request bodies in the request factory.
+* Removing the requirement that HTTPS requests needed a Cache-Control: public directive to be cacheable.
+* [Http] Adding support for Content-Type in multipart POST uploads per upload
+* [Http] Added support for uploading multiple files using the same name (foo[0], foo[1])
+* Adding more POST data operations for easier manipulation of POST data.
+* You can now set empty POST fields.
+* The body of a request is only shown on EntityEnclosingRequest objects that do not use POST files.
+* Split the Guzzle\Service\Inspector::validateConfig method into two methods. One to initialize when a command is created, and one to validate.
+* CS updates
+
+## 2.6.2 - 2012-05-19
+
+* [Http] Better handling of nested scope requests in CurlMulti. Requests are now always prepares in the send() method rather than the addRequest() method.
+
+## 2.6.1 - 2012-05-19
+
+* [BC] Removing 'path' support in service descriptions. Use 'uri'.
+* [BC] Guzzle\Service\Inspector::parseDocBlock is now protected. Adding getApiParamsForClass() with cache.
+* [BC] Removing Guzzle\Common\NullObject. Use https://github.com/mtdowling/NullObject if you need it.
+* [BC] Removing Guzzle\Common\XmlElement.
+* All commands, both dynamic and concrete, have ApiCommand objects.
+* Adding a fix for CurlMulti so that if all of the connections encounter some sort of curl error, then the loop exits.
+* Adding checks to EntityEnclosingRequest so that empty POST files and fields are ignored.
+* Making the method signature of Guzzle\Service\Builder\ServiceBuilder::factory more flexible.
+
+## 2.6.0 - 2012-05-15
+
+* [BC] Moving Guzzle\Service\Builder to Guzzle\Service\Builder\ServiceBuilder
+* [BC] Executing a Command returns the result of the command rather than the command
+* [BC] Moving all HTTP parsing logic to Guzzle\Http\Parsers. Allows for faster C implementations if needed.
+* [BC] Changing the Guzzle\Http\Message\Response::setProtocol() method to accept a protocol and version in separate args.
+* [BC] Moving ResourceIterator* to Guzzle\Service\Resource
+* [BC] Completely refactored ResourceIterators to iterate over a cloned command object
+* [BC] Moved Guzzle\Http\UriTemplate to Guzzle\Http\Parser\UriTemplate\UriTemplate
+* [BC] Guzzle\Guzzle is now deprecated
+* Moving Guzzle\Common\Guzzle::inject to Guzzle\Common\Collection::inject
+* Adding Guzzle\Version class to give version information about Guzzle
+* Adding Guzzle\Http\Utils class to provide getDefaultUserAgent() and getHttpDate()
+* Adding Guzzle\Curl\CurlVersion to manage caching curl_version() data
+* ServiceDescription and ServiceBuilder are now cacheable using similar configs
+* Changing the format of XML and JSON service builder configs. Backwards compatible.
+* Cleaned up Cookie parsing
+* Trimming the default Guzzle User-Agent header
+* Adding a setOnComplete() method to Commands that is called when a command completes
+* Keeping track of requests that were mocked in the MockPlugin
+* Fixed a caching bug in the CacheAdapterFactory
+* Inspector objects can be injected into a Command object
+* Refactoring a lot of code and tests to be case insensitive when dealing with headers
+* Adding Guzzle\Http\Message\HeaderComparison for easy comparison of HTTP headers using a DSL
+* Adding the ability to set global option overrides to service builder configs
+* Adding the ability to include other service builder config files from within XML and JSON files
+* Moving the parseQuery method out of Url and on to QueryString::fromString() as a static factory method.
+
+## 2.5.0 - 2012-05-08
+
+* Major performance improvements
+* [BC] Simplifying Guzzle\Common\Collection. Please check to see if you are using features that are now deprecated.
+* [BC] Using a custom validation system that allows a flyweight implementation for much faster validation. No longer using Symfony2 Validation component.
+* [BC] No longer supporting "{{ }}" for injecting into command or UriTemplates. Use "{}"
+* Added the ability to passed parameters to all requests created by a client
+* Added callback functionality to the ExponentialBackoffPlugin
+* Using microtime in ExponentialBackoffPlugin to allow more granular backoff strategies.
+* Rewinding request stream bodies when retrying requests
+* Exception is thrown when JSON response body cannot be decoded
+* Added configurable magic method calls to clients and commands. This is off by default.
+* Fixed a defect that added a hash to every parsed URL part
+* Fixed duplicate none generation for OauthPlugin.
+* Emitting an event each time a client is generated by a ServiceBuilder
+* Using an ApiParams object instead of a Collection for parameters of an ApiCommand
+* cache.* request parameters should be renamed to params.cache.*
+* Added the ability to set arbitrary curl options on requests (disable_wire, progress, etc.). See CurlHandle.
+* Added the ability to disable type validation of service descriptions
+* ServiceDescriptions and ServiceBuilders are now Serializable
diff --git a/server/vendor/guzzlehttp/guzzle/LICENSE b/server/vendor/guzzlehttp/guzzle/LICENSE
new file mode 100644
index 0000000..9af9fba
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2011-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/server/vendor/guzzlehttp/guzzle/README.md b/server/vendor/guzzlehttp/guzzle/README.md
new file mode 100644
index 0000000..3af1cc3
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/README.md
@@ -0,0 +1,90 @@
+Guzzle, PHP HTTP client
+=======================
+
+[![Build Status](https://secure.travis-ci.org/guzzle/guzzle.svg?branch=master)](http://travis-ci.org/guzzle/guzzle)
+
+Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and
+trivial to integrate with web services.
+
+- Simple interface for building query strings, POST requests, streaming large
+ uploads, streaming large downloads, using HTTP cookies, uploading JSON data,
+ etc...
+- Can send both synchronous and asynchronous requests using the same interface.
+- Uses PSR-7 interfaces for requests, responses, and streams. This allows you
+ to utilize other PSR-7 compatible libraries with Guzzle.
+- Abstracts away the underlying HTTP transport, allowing you to write
+ environment and transport agnostic code; i.e., no hard dependency on cURL,
+ PHP streams, sockets, or non-blocking event loops.
+- Middleware system allows you to augment and compose client behavior.
+
+```php
+$client = new GuzzleHttp\Client();
+$res = $client->request('GET', 'https://api.github.com/user', [
+ 'auth' => ['user', 'pass']
+]);
+echo $res->getStatusCode();
+// 200
+echo $res->getHeader('content-type');
+// 'application/json; charset=utf8'
+echo $res->getBody();
+// {"type":"User"...'
+
+// Send an asynchronous request.
+$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org');
+$promise = $client->sendAsync($request)->then(function ($response) {
+ echo 'I completed! ' . $response->getBody();
+});
+$promise->wait();
+```
+
+## Help and docs
+
+- [Documentation](http://guzzlephp.org/)
+- [stackoverflow](http://stackoverflow.com/questions/tagged/guzzle)
+- [Gitter](https://gitter.im/guzzle/guzzle)
+
+
+## Installing Guzzle
+
+The recommended way to install Guzzle is through
+[Composer](http://getcomposer.org).
+
+```bash
+# Install Composer
+curl -sS https://getcomposer.org/installer | php
+```
+
+Next, run the Composer command to install the latest stable version of Guzzle:
+
+```bash
+composer.phar require guzzlehttp/guzzle
+```
+
+After installing, you need to require Composer's autoloader:
+
+```php
+require 'vendor/autoload.php';
+```
+
+You can then later update Guzzle using composer:
+
+ ```bash
+composer.phar update
+ ```
+
+
+## Version Guidance
+
+| Version | Status | Packagist | Namespace | Repo | Docs | PSR-7 |
+|---------|-------------|---------------------|--------------|---------------------|---------------------|-------|
+| 3.x | EOL | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No |
+| 4.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | N/A | N/A | No |
+| 5.x | Maintained | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No |
+| 6.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes |
+
+[guzzle-3-repo]: https://github.com/guzzle/guzzle3
+[guzzle-5-repo]: https://github.com/guzzle/guzzle/tree/5.3
+[guzzle-6-repo]: https://github.com/guzzle/guzzle
+[guzzle-3-docs]: http://guzzle3.readthedocs.org/en/latest/
+[guzzle-5-docs]: http://guzzle.readthedocs.org/en/5.3/
+[guzzle-6-docs]: http://guzzle.readthedocs.org/en/latest/
diff --git a/server/vendor/guzzlehttp/guzzle/UPGRADING.md b/server/vendor/guzzlehttp/guzzle/UPGRADING.md
new file mode 100644
index 0000000..9e31ddc
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/UPGRADING.md
@@ -0,0 +1,1203 @@
+Guzzle Upgrade Guide
+====================
+
+5.0 to 6.0
+----------
+
+Guzzle now uses [PSR-7](http://www.php-fig.org/psr/psr-7/) for HTTP messages.
+Due to the fact that these messages are immutable, this prompted a refactoring
+of Guzzle to use a middleware based system rather than an event system. Any
+HTTP message interaction (e.g., `GuzzleHttp\Message\Request`) need to be
+updated to work with the new immutable PSR-7 request and response objects. Any
+event listeners or subscribers need to be updated to become middleware
+functions that wrap handlers (or are injected into a
+`GuzzleHttp\HandlerStack`).
+
+- Removed `GuzzleHttp\BatchResults`
+- Removed `GuzzleHttp\Collection`
+- Removed `GuzzleHttp\HasDataTrait`
+- Removed `GuzzleHttp\ToArrayInterface`
+- The `guzzlehttp/streams` dependency has been removed. Stream functionality
+ is now present in the `GuzzleHttp\Psr7` namespace provided by the
+ `guzzlehttp/psr7` package.
+- Guzzle no longer uses ReactPHP promises and now uses the
+ `guzzlehttp/promises` library. We use a custom promise library for three
+ significant reasons:
+ 1. React promises (at the time of writing this) are recursive. Promise
+ chaining and promise resolution will eventually blow the stack. Guzzle
+ promises are not recursive as they use a sort of trampolining technique.
+ Note: there has been movement in the React project to modify promises to
+ no longer utilize recursion.
+ 2. Guzzle needs to have the ability to synchronously block on a promise to
+ wait for a result. Guzzle promises allows this functionality (and does
+ not require the use of recursion).
+ 3. Because we need to be able to wait on a result, doing so using React
+ promises requires wrapping react promises with RingPHP futures. This
+ overhead is no longer needed, reducing stack sizes, reducing complexity,
+ and improving performance.
+- `GuzzleHttp\Mimetypes` has been moved to a function in
+ `GuzzleHttp\Psr7\mimetype_from_extension` and
+ `GuzzleHttp\Psr7\mimetype_from_filename`.
+- `GuzzleHttp\Query` and `GuzzleHttp\QueryParser` have been removed. Query
+ strings must now be passed into request objects as strings, or provided to
+ the `query` request option when creating requests with clients. The `query`
+ option uses PHP's `http_build_query` to convert an array to a string. If you
+ need a different serialization technique, you will need to pass the query
+ string in as a string. There are a couple helper functions that will make
+ working with query strings easier: `GuzzleHttp\Psr7\parse_query` and
+ `GuzzleHttp\Psr7\build_query`.
+- Guzzle no longer has a dependency on RingPHP. Due to the use of a middleware
+ system based on PSR-7, using RingPHP and it's middleware system as well adds
+ more complexity than the benefits it provides. All HTTP handlers that were
+ present in RingPHP have been modified to work directly with PSR-7 messages
+ and placed in the `GuzzleHttp\Handler` namespace. This significantly reduces
+ complexity in Guzzle, removes a dependency, and improves performance. RingPHP
+ will be maintained for Guzzle 5 support, but will no longer be a part of
+ Guzzle 6.
+- As Guzzle now uses a middleware based systems the event system and RingPHP
+ integration has been removed. Note: while the event system has been removed,
+ it is possible to add your own type of event system that is powered by the
+ middleware system.
+ - Removed the `Event` namespace.
+ - Removed the `Subscriber` namespace.
+ - Removed `Transaction` class
+ - Removed `RequestFsm`
+ - Removed `RingBridge`
+ - `GuzzleHttp\Subscriber\Cookie` is now provided by
+ `GuzzleHttp\Middleware::cookies`
+ - `GuzzleHttp\Subscriber\HttpError` is now provided by
+ `GuzzleHttp\Middleware::httpError`
+ - `GuzzleHttp\Subscriber\History` is now provided by
+ `GuzzleHttp\Middleware::history`
+ - `GuzzleHttp\Subscriber\Mock` is now provided by
+ `GuzzleHttp\Handler\MockHandler`
+ - `GuzzleHttp\Subscriber\Prepare` is now provided by
+ `GuzzleHttp\PrepareBodyMiddleware`
+ - `GuzzleHttp\Subscriber\Redirect` is now provided by
+ `GuzzleHttp\RedirectMiddleware`
+- Guzzle now uses `Psr\Http\Message\UriInterface` (implements in
+ `GuzzleHttp\Psr7\Uri`) for URI support. `GuzzleHttp\Url` is now gone.
+- Static functions in `GuzzleHttp\Utils` have been moved to namespaced
+ functions under the `GuzzleHttp` namespace. This requires either a Composer
+ based autoloader or you to include functions.php.
+- `GuzzleHttp\ClientInterface::getDefaultOption` has been renamed to
+ `GuzzleHttp\ClientInterface::getConfig`.
+- `GuzzleHttp\ClientInterface::setDefaultOption` has been removed.
+- The `json` and `xml` methods of response objects has been removed. With the
+ migration to strictly adhering to PSR-7 as the interface for Guzzle messages,
+ adding methods to message interfaces would actually require Guzzle messages
+ to extend from PSR-7 messages rather then work with them directly.
+
+## Migrating to middleware
+
+The change to PSR-7 unfortunately required significant refactoring to Guzzle
+due to the fact that PSR-7 messages are immutable. Guzzle 5 relied on an event
+system from plugins. The event system relied on mutability of HTTP messages and
+side effects in order to work. With immutable messages, you have to change your
+workflow to become more about either returning a value (e.g., functional
+middlewares) or setting a value on an object. Guzzle v6 has chosen the
+functional middleware approach.
+
+Instead of using the event system to listen for things like the `before` event,
+you now create a stack based middleware function that intercepts a request on
+the way in and the promise of the response on the way out. This is a much
+simpler and more predictable approach than the event system and works nicely
+with PSR-7 middleware. Due to the use of promises, the middleware system is
+also asynchronous.
+
+v5:
+
+```php
+use GuzzleHttp\Event\BeforeEvent;
+$client = new GuzzleHttp\Client();
+// Get the emitter and listen to the before event.
+$client->getEmitter()->on('before', function (BeforeEvent $e) {
+ // Guzzle v5 events relied on mutation
+ $e->getRequest()->setHeader('X-Foo', 'Bar');
+});
+```
+
+v6:
+
+In v6, you can modify the request before it is sent using the `mapRequest`
+middleware. The idiomatic way in v6 to modify the request/response lifecycle is
+to setup a handler middleware stack up front and inject the handler into a
+client.
+
+```php
+use GuzzleHttp\Middleware;
+// Create a handler stack that has all of the default middlewares attached
+$handler = GuzzleHttp\HandlerStack::create();
+// Push the handler onto the handler stack
+$handler->push(Middleware::mapRequest(function (RequestInterface $request) {
+ // Notice that we have to return a request object
+ return $request->withHeader('X-Foo', 'Bar');
+});
+// Inject the handler into the client
+$client = new GuzzleHttp\Client(['handler' => $handler]);
+```
+
+## POST Requests
+
+This version added the [`form_params`](http://guzzle.readthedocs.org/en/latest/request-options.html#form_params)
+and `multipart` request options. `form_params` is an associative array of
+strings or array of strings and is used to serialize an
+`application/x-www-form-urlencoded` POST request. The
+[`multipart`](http://guzzle.readthedocs.org/en/latest/request-options.html#multipart)
+option is now used to send a multipart/form-data POST request.
+
+`GuzzleHttp\Post\PostFile` has been removed. Use the `multipart` option to add
+POST files to a multipart/form-data request.
+
+The `body` option no longer accepts an array to send POST requests. Please use
+`multipart` or `form_params` instead.
+
+The `base_url` option has been renamed to `base_uri`.
+
+4.x to 5.0
+----------
+
+## Rewritten Adapter Layer
+
+Guzzle now uses [RingPHP](http://ringphp.readthedocs.org/en/latest) to send
+HTTP requests. The `adapter` option in a `GuzzleHttp\Client` constructor
+is still supported, but it has now been renamed to `handler`. Instead of
+passing a `GuzzleHttp\Adapter\AdapterInterface`, you must now pass a PHP
+`callable` that follows the RingPHP specification.
+
+## Removed Fluent Interfaces
+
+[Fluent interfaces were removed](http://ocramius.github.io/blog/fluent-interfaces-are-evil)
+from the following classes:
+
+- `GuzzleHttp\Collection`
+- `GuzzleHttp\Url`
+- `GuzzleHttp\Query`
+- `GuzzleHttp\Post\PostBody`
+- `GuzzleHttp\Cookie\SetCookie`
+
+## Removed functions.php
+
+Removed "functions.php", so that Guzzle is truly PSR-4 compliant. The following
+functions can be used as replacements.
+
+- `GuzzleHttp\json_decode` -> `GuzzleHttp\Utils::jsonDecode`
+- `GuzzleHttp\get_path` -> `GuzzleHttp\Utils::getPath`
+- `GuzzleHttp\Utils::setPath` -> `GuzzleHttp\set_path`
+- `GuzzleHttp\Pool::batch` -> `GuzzleHttp\batch`. This function is, however,
+ deprecated in favor of using `GuzzleHttp\Pool::batch()`.
+
+The "procedural" global client has been removed with no replacement (e.g.,
+`GuzzleHttp\get()`, `GuzzleHttp\post()`, etc.). Use a `GuzzleHttp\Client`
+object as a replacement.
+
+## `throwImmediately` has been removed
+
+The concept of "throwImmediately" has been removed from exceptions and error
+events. This control mechanism was used to stop a transfer of concurrent
+requests from completing. This can now be handled by throwing the exception or
+by cancelling a pool of requests or each outstanding future request
+individually.
+
+## headers event has been removed
+
+Removed the "headers" event. This event was only useful for changing the
+body a response once the headers of the response were known. You can implement
+a similar behavior in a number of ways. One example might be to use a
+FnStream that has access to the transaction being sent. For example, when the
+first byte is written, you could check if the response headers match your
+expectations, and if so, change the actual stream body that is being
+written to.
+
+## Updates to HTTP Messages
+
+Removed the `asArray` parameter from
+`GuzzleHttp\Message\MessageInterface::getHeader`. If you want to get a header
+value as an array, then use the newly added `getHeaderAsArray()` method of
+`MessageInterface`. This change makes the Guzzle interfaces compatible with
+the PSR-7 interfaces.
+
+3.x to 4.0
+----------
+
+## Overarching changes:
+
+- Now requires PHP 5.4 or greater.
+- No longer requires cURL to send requests.
+- Guzzle no longer wraps every exception it throws. Only exceptions that are
+ recoverable are now wrapped by Guzzle.
+- Various namespaces have been removed or renamed.
+- No longer requiring the Symfony EventDispatcher. A custom event dispatcher
+ based on the Symfony EventDispatcher is
+ now utilized in `GuzzleHttp\Event\EmitterInterface` (resulting in significant
+ speed and functionality improvements).
+
+Changes per Guzzle 3.x namespace are described below.
+
+## Batch
+
+The `Guzzle\Batch` namespace has been removed. This is best left to
+third-parties to implement on top of Guzzle's core HTTP library.
+
+## Cache
+
+The `Guzzle\Cache` namespace has been removed. (Todo: No suitable replacement
+has been implemented yet, but hoping to utilize a PSR cache interface).
+
+## Common
+
+- Removed all of the wrapped exceptions. It's better to use the standard PHP
+ library for unrecoverable exceptions.
+- `FromConfigInterface` has been removed.
+- `Guzzle\Common\Version` has been removed. The VERSION constant can be found
+ at `GuzzleHttp\ClientInterface::VERSION`.
+
+### Collection
+
+- `getAll` has been removed. Use `toArray` to convert a collection to an array.
+- `inject` has been removed.
+- `keySearch` has been removed.
+- `getPath` no longer supports wildcard expressions. Use something better like
+ JMESPath for this.
+- `setPath` now supports appending to an existing array via the `[]` notation.
+
+### Events
+
+Guzzle no longer requires Symfony's EventDispatcher component. Guzzle now uses
+`GuzzleHttp\Event\Emitter`.
+
+- `Symfony\Component\EventDispatcher\EventDispatcherInterface` is replaced by
+ `GuzzleHttp\Event\EmitterInterface`.
+- `Symfony\Component\EventDispatcher\EventDispatcher` is replaced by
+ `GuzzleHttp\Event\Emitter`.
+- `Symfony\Component\EventDispatcher\Event` is replaced by
+ `GuzzleHttp\Event\Event`, and Guzzle now has an EventInterface in
+ `GuzzleHttp\Event\EventInterface`.
+- `AbstractHasDispatcher` has moved to a trait, `HasEmitterTrait`, and
+ `HasDispatcherInterface` has moved to `HasEmitterInterface`. Retrieving the
+ event emitter of a request, client, etc. now uses the `getEmitter` method
+ rather than the `getDispatcher` method.
+
+#### Emitter
+
+- Use the `once()` method to add a listener that automatically removes itself
+ the first time it is invoked.
+- Use the `listeners()` method to retrieve a list of event listeners rather than
+ the `getListeners()` method.
+- Use `emit()` instead of `dispatch()` to emit an event from an emitter.
+- Use `attach()` instead of `addSubscriber()` and `detach()` instead of
+ `removeSubscriber()`.
+
+```php
+$mock = new Mock();
+// 3.x
+$request->getEventDispatcher()->addSubscriber($mock);
+$request->getEventDispatcher()->removeSubscriber($mock);
+// 4.x
+$request->getEmitter()->attach($mock);
+$request->getEmitter()->detach($mock);
+```
+
+Use the `on()` method to add a listener rather than the `addListener()` method.
+
+```php
+// 3.x
+$request->getEventDispatcher()->addListener('foo', function (Event $event) { /* ... */ } );
+// 4.x
+$request->getEmitter()->on('foo', function (Event $event, $name) { /* ... */ } );
+```
+
+## Http
+
+### General changes
+
+- The cacert.pem certificate has been moved to `src/cacert.pem`.
+- Added the concept of adapters that are used to transfer requests over the
+ wire.
+- Simplified the event system.
+- Sending requests in parallel is still possible, but batching is no longer a
+ concept of the HTTP layer. Instead, you must use the `complete` and `error`
+ events to asynchronously manage parallel request transfers.
+- `Guzzle\Http\Url` has moved to `GuzzleHttp\Url`.
+- `Guzzle\Http\QueryString` has moved to `GuzzleHttp\Query`.
+- QueryAggregators have been rewritten so that they are simply callable
+ functions.
+- `GuzzleHttp\StaticClient` has been removed. Use the functions provided in
+ `functions.php` for an easy to use static client instance.
+- Exceptions in `GuzzleHttp\Exception` have been updated to all extend from
+ `GuzzleHttp\Exception\TransferException`.
+
+### Client
+
+Calling methods like `get()`, `post()`, `head()`, etc. no longer create and
+return a request, but rather creates a request, sends the request, and returns
+the response.
+
+```php
+// 3.0
+$request = $client->get('/');
+$response = $request->send();
+
+// 4.0
+$response = $client->get('/');
+
+// or, to mirror the previous behavior
+$request = $client->createRequest('GET', '/');
+$response = $client->send($request);
+```
+
+`GuzzleHttp\ClientInterface` has changed.
+
+- The `send` method no longer accepts more than one request. Use `sendAll` to
+ send multiple requests in parallel.
+- `setUserAgent()` has been removed. Use a default request option instead. You
+ could, for example, do something like:
+ `$client->setConfig('defaults/headers/User-Agent', 'Foo/Bar ' . $client::getDefaultUserAgent())`.
+- `setSslVerification()` has been removed. Use default request options instead,
+ like `$client->setConfig('defaults/verify', true)`.
+
+`GuzzleHttp\Client` has changed.
+
+- The constructor now accepts only an associative array. You can include a
+ `base_url` string or array to use a URI template as the base URL of a client.
+ You can also specify a `defaults` key that is an associative array of default
+ request options. You can pass an `adapter` to use a custom adapter,
+ `batch_adapter` to use a custom adapter for sending requests in parallel, or
+ a `message_factory` to change the factory used to create HTTP requests and
+ responses.
+- The client no longer emits a `client.create_request` event.
+- Creating requests with a client no longer automatically utilize a URI
+ template. You must pass an array into a creational method (e.g.,
+ `createRequest`, `get`, `put`, etc.) in order to expand a URI template.
+
+### Messages
+
+Messages no longer have references to their counterparts (i.e., a request no
+longer has a reference to it's response, and a response no loger has a
+reference to its request). This association is now managed through a
+`GuzzleHttp\Adapter\TransactionInterface` object. You can get references to
+these transaction objects using request events that are emitted over the
+lifecycle of a request.
+
+#### Requests with a body
+
+- `GuzzleHttp\Message\EntityEnclosingRequest` and
+ `GuzzleHttp\Message\EntityEnclosingRequestInterface` have been removed. The
+ separation between requests that contain a body and requests that do not
+ contain a body has been removed, and now `GuzzleHttp\Message\RequestInterface`
+ handles both use cases.
+- Any method that previously accepts a `GuzzleHttp\Response` object now accept a
+ `GuzzleHttp\Message\ResponseInterface`.
+- `GuzzleHttp\Message\RequestFactoryInterface` has been renamed to
+ `GuzzleHttp\Message\MessageFactoryInterface`. This interface is used to create
+ both requests and responses and is implemented in
+ `GuzzleHttp\Message\MessageFactory`.
+- POST field and file methods have been removed from the request object. You
+ must now use the methods made available to `GuzzleHttp\Post\PostBodyInterface`
+ to control the format of a POST body. Requests that are created using a
+ standard `GuzzleHttp\Message\MessageFactoryInterface` will automatically use
+ a `GuzzleHttp\Post\PostBody` body if the body was passed as an array or if
+ the method is POST and no body is provided.
+
+```php
+$request = $client->createRequest('POST', '/');
+$request->getBody()->setField('foo', 'bar');
+$request->getBody()->addFile(new PostFile('file_key', fopen('/path/to/content', 'r')));
+```
+
+#### Headers
+
+- `GuzzleHttp\Message\Header` has been removed. Header values are now simply
+ represented by an array of values or as a string. Header values are returned
+ as a string by default when retrieving a header value from a message. You can
+ pass an optional argument of `true` to retrieve a header value as an array
+ of strings instead of a single concatenated string.
+- `GuzzleHttp\PostFile` and `GuzzleHttp\PostFileInterface` have been moved to
+ `GuzzleHttp\Post`. This interface has been simplified and now allows the
+ addition of arbitrary headers.
+- Custom headers like `GuzzleHttp\Message\Header\Link` have been removed. Most
+ of the custom headers are now handled separately in specific
+ subscribers/plugins, and `GuzzleHttp\Message\HeaderValues::parseParams()` has
+ been updated to properly handle headers that contain parameters (like the
+ `Link` header).
+
+#### Responses
+
+- `GuzzleHttp\Message\Response::getInfo()` and
+ `GuzzleHttp\Message\Response::setInfo()` have been removed. Use the event
+ system to retrieve this type of information.
+- `GuzzleHttp\Message\Response::getRawHeaders()` has been removed.
+- `GuzzleHttp\Message\Response::getMessage()` has been removed.
+- `GuzzleHttp\Message\Response::calculateAge()` and other cache specific
+ methods have moved to the CacheSubscriber.
+- Header specific helper functions like `getContentMd5()` have been removed.
+ Just use `getHeader('Content-MD5')` instead.
+- `GuzzleHttp\Message\Response::setRequest()` and
+ `GuzzleHttp\Message\Response::getRequest()` have been removed. Use the event
+ system to work with request and response objects as a transaction.
+- `GuzzleHttp\Message\Response::getRedirectCount()` has been removed. Use the
+ Redirect subscriber instead.
+- `GuzzleHttp\Message\Response::isSuccessful()` and other related methods have
+ been removed. Use `getStatusCode()` instead.
+
+#### Streaming responses
+
+Streaming requests can now be created by a client directly, returning a
+`GuzzleHttp\Message\ResponseInterface` object that contains a body stream
+referencing an open PHP HTTP stream.
+
+```php
+// 3.0
+use Guzzle\Stream\PhpStreamRequestFactory;
+$request = $client->get('/');
+$factory = new PhpStreamRequestFactory();
+$stream = $factory->fromRequest($request);
+$data = $stream->read(1024);
+
+// 4.0
+$response = $client->get('/', ['stream' => true]);
+// Read some data off of the stream in the response body
+$data = $response->getBody()->read(1024);
+```
+
+#### Redirects
+
+The `configureRedirects()` method has been removed in favor of a
+`allow_redirects` request option.
+
+```php
+// Standard redirects with a default of a max of 5 redirects
+$request = $client->createRequest('GET', '/', ['allow_redirects' => true]);
+
+// Strict redirects with a custom number of redirects
+$request = $client->createRequest('GET', '/', [
+ 'allow_redirects' => ['max' => 5, 'strict' => true]
+]);
+```
+
+#### EntityBody
+
+EntityBody interfaces and classes have been removed or moved to
+`GuzzleHttp\Stream`. All classes and interfaces that once required
+`GuzzleHttp\EntityBodyInterface` now require
+`GuzzleHttp\Stream\StreamInterface`. Creating a new body for a request no
+longer uses `GuzzleHttp\EntityBody::factory` but now uses
+`GuzzleHttp\Stream\Stream::factory` or even better:
+`GuzzleHttp\Stream\create()`.
+
+- `Guzzle\Http\EntityBodyInterface` is now `GuzzleHttp\Stream\StreamInterface`
+- `Guzzle\Http\EntityBody` is now `GuzzleHttp\Stream\Stream`
+- `Guzzle\Http\CachingEntityBody` is now `GuzzleHttp\Stream\CachingStream`
+- `Guzzle\Http\ReadLimitEntityBody` is now `GuzzleHttp\Stream\LimitStream`
+- `Guzzle\Http\IoEmittyinEntityBody` has been removed.
+
+#### Request lifecycle events
+
+Requests previously submitted a large number of requests. The number of events
+emitted over the lifecycle of a request has been significantly reduced to make
+it easier to understand how to extend the behavior of a request. All events
+emitted during the lifecycle of a request now emit a custom
+`GuzzleHttp\Event\EventInterface` object that contains context providing
+methods and a way in which to modify the transaction at that specific point in
+time (e.g., intercept the request and set a response on the transaction).
+
+- `request.before_send` has been renamed to `before` and now emits a
+ `GuzzleHttp\Event\BeforeEvent`
+- `request.complete` has been renamed to `complete` and now emits a
+ `GuzzleHttp\Event\CompleteEvent`.
+- `request.sent` has been removed. Use `complete`.
+- `request.success` has been removed. Use `complete`.
+- `error` is now an event that emits a `GuzzleHttp\Event\ErrorEvent`.
+- `request.exception` has been removed. Use `error`.
+- `request.receive.status_line` has been removed.
+- `curl.callback.progress` has been removed. Use a custom `StreamInterface` to
+ maintain a status update.
+- `curl.callback.write` has been removed. Use a custom `StreamInterface` to
+ intercept writes.
+- `curl.callback.read` has been removed. Use a custom `StreamInterface` to
+ intercept reads.
+
+`headers` is a new event that is emitted after the response headers of a
+request have been received before the body of the response is downloaded. This
+event emits a `GuzzleHttp\Event\HeadersEvent`.
+
+You can intercept a request and inject a response using the `intercept()` event
+of a `GuzzleHttp\Event\BeforeEvent`, `GuzzleHttp\Event\CompleteEvent`, and
+`GuzzleHttp\Event\ErrorEvent` event.
+
+See: http://docs.guzzlephp.org/en/latest/events.html
+
+## Inflection
+
+The `Guzzle\Inflection` namespace has been removed. This is not a core concern
+of Guzzle.
+
+## Iterator
+
+The `Guzzle\Iterator` namespace has been removed.
+
+- `Guzzle\Iterator\AppendIterator`, `Guzzle\Iterator\ChunkedIterator`, and
+ `Guzzle\Iterator\MethodProxyIterator` are nice, but not a core requirement of
+ Guzzle itself.
+- `Guzzle\Iterator\FilterIterator` is no longer needed because an equivalent
+ class is shipped with PHP 5.4.
+- `Guzzle\Iterator\MapIterator` is not really needed when using PHP 5.5 because
+ it's easier to just wrap an iterator in a generator that maps values.
+
+For a replacement of these iterators, see https://github.com/nikic/iter
+
+## Log
+
+The LogPlugin has moved to https://github.com/guzzle/log-subscriber. The
+`Guzzle\Log` namespace has been removed. Guzzle now relies on
+`Psr\Log\LoggerInterface` for all logging. The MessageFormatter class has been
+moved to `GuzzleHttp\Subscriber\Log\Formatter`.
+
+## Parser
+
+The `Guzzle\Parser` namespace has been removed. This was previously used to
+make it possible to plug in custom parsers for cookies, messages, URI
+templates, and URLs; however, this level of complexity is not needed in Guzzle
+so it has been removed.
+
+- Cookie: Cookie parsing logic has been moved to
+ `GuzzleHttp\Cookie\SetCookie::fromString`.
+- Message: Message parsing logic for both requests and responses has been moved
+ to `GuzzleHttp\Message\MessageFactory::fromMessage`. Message parsing is only
+ used in debugging or deserializing messages, so it doesn't make sense for
+ Guzzle as a library to add this level of complexity to parsing messages.
+- UriTemplate: URI template parsing has been moved to
+ `GuzzleHttp\UriTemplate`. The Guzzle library will automatically use the PECL
+ URI template library if it is installed.
+- Url: URL parsing is now performed in `GuzzleHttp\Url::fromString` (previously
+ it was `Guzzle\Http\Url::factory()`). If custom URL parsing is necessary,
+ then developers are free to subclass `GuzzleHttp\Url`.
+
+## Plugin
+
+The `Guzzle\Plugin` namespace has been renamed to `GuzzleHttp\Subscriber`.
+Several plugins are shipping with the core Guzzle library under this namespace.
+
+- `GuzzleHttp\Subscriber\Cookie`: Replaces the old CookiePlugin. Cookie jar
+ code has moved to `GuzzleHttp\Cookie`.
+- `GuzzleHttp\Subscriber\History`: Replaces the old HistoryPlugin.
+- `GuzzleHttp\Subscriber\HttpError`: Throws errors when a bad HTTP response is
+ received.
+- `GuzzleHttp\Subscriber\Mock`: Replaces the old MockPlugin.
+- `GuzzleHttp\Subscriber\Prepare`: Prepares the body of a request just before
+ sending. This subscriber is attached to all requests by default.
+- `GuzzleHttp\Subscriber\Redirect`: Replaces the RedirectPlugin.
+
+The following plugins have been removed (third-parties are free to re-implement
+these if needed):
+
+- `GuzzleHttp\Plugin\Async` has been removed.
+- `GuzzleHttp\Plugin\CurlAuth` has been removed.
+- `GuzzleHttp\Plugin\ErrorResponse\ErrorResponsePlugin` has been removed. This
+ functionality should instead be implemented with event listeners that occur
+ after normal response parsing occurs in the guzzle/command package.
+
+The following plugins are not part of the core Guzzle package, but are provided
+in separate repositories:
+
+- `Guzzle\Http\Plugin\BackoffPlugin` has been rewritten to be muchs simpler
+ to build custom retry policies using simple functions rather than various
+ chained classes. See: https://github.com/guzzle/retry-subscriber
+- `Guzzle\Http\Plugin\Cache\CachePlugin` has moved to
+ https://github.com/guzzle/cache-subscriber
+- `Guzzle\Http\Plugin\Log\LogPlugin` has moved to
+ https://github.com/guzzle/log-subscriber
+- `Guzzle\Http\Plugin\Md5\Md5Plugin` has moved to
+ https://github.com/guzzle/message-integrity-subscriber
+- `Guzzle\Http\Plugin\Mock\MockPlugin` has moved to
+ `GuzzleHttp\Subscriber\MockSubscriber`.
+- `Guzzle\Http\Plugin\Oauth\OauthPlugin` has moved to
+ https://github.com/guzzle/oauth-subscriber
+
+## Service
+
+The service description layer of Guzzle has moved into two separate packages:
+
+- http://github.com/guzzle/command Provides a high level abstraction over web
+ services by representing web service operations using commands.
+- http://github.com/guzzle/guzzle-services Provides an implementation of
+ guzzle/command that provides request serialization and response parsing using
+ Guzzle service descriptions.
+
+## Stream
+
+Stream have moved to a separate package available at
+https://github.com/guzzle/streams.
+
+`Guzzle\Stream\StreamInterface` has been given a large update to cleanly take
+on the responsibilities of `Guzzle\Http\EntityBody` and
+`Guzzle\Http\EntityBodyInterface` now that they have been removed. The number
+of methods implemented by the `StreamInterface` has been drastically reduced to
+allow developers to more easily extend and decorate stream behavior.
+
+## Removed methods from StreamInterface
+
+- `getStream` and `setStream` have been removed to better encapsulate streams.
+- `getMetadata` and `setMetadata` have been removed in favor of
+ `GuzzleHttp\Stream\MetadataStreamInterface`.
+- `getWrapper`, `getWrapperData`, `getStreamType`, and `getUri` have all been
+ removed. This data is accessible when
+ using streams that implement `GuzzleHttp\Stream\MetadataStreamInterface`.
+- `rewind` has been removed. Use `seek(0)` for a similar behavior.
+
+## Renamed methods
+
+- `detachStream` has been renamed to `detach`.
+- `feof` has been renamed to `eof`.
+- `ftell` has been renamed to `tell`.
+- `readLine` has moved from an instance method to a static class method of
+ `GuzzleHttp\Stream\Stream`.
+
+## Metadata streams
+
+`GuzzleHttp\Stream\MetadataStreamInterface` has been added to denote streams
+that contain additional metadata accessible via `getMetadata()`.
+`GuzzleHttp\Stream\StreamInterface::getMetadata` and
+`GuzzleHttp\Stream\StreamInterface::setMetadata` have been removed.
+
+## StreamRequestFactory
+
+The entire concept of the StreamRequestFactory has been removed. The way this
+was used in Guzzle 3 broke the actual interface of sending streaming requests
+(instead of getting back a Response, you got a StreamInterface). Streeaming
+PHP requests are now implemented throught the `GuzzleHttp\Adapter\StreamAdapter`.
+
+3.6 to 3.7
+----------
+
+### Deprecations
+
+- You can now enable E_USER_DEPRECATED warnings to see if you are using any deprecated methods.:
+
+```php
+\Guzzle\Common\Version::$emitWarnings = true;
+```
+
+The following APIs and options have been marked as deprecated:
+
+- Marked `Guzzle\Http\Message\Request::isResponseBodyRepeatable()` as deprecated. Use `$request->getResponseBody()->isRepeatable()` instead.
+- Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead.
+- Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead.
+- Marked `Guzzle\Http\Message\Request::setIsRedirect()` as deprecated. Use the HistoryPlugin instead.
+- Marked `Guzzle\Http\Message\Request::isRedirect()` as deprecated. Use the HistoryPlugin instead.
+- Marked `Guzzle\Cache\CacheAdapterFactory::factory()` as deprecated
+- Marked `Guzzle\Service\Client::enableMagicMethods()` as deprecated. Magic methods can no longer be disabled on a Guzzle\Service\Client.
+- Marked `Guzzle\Parser\Url\UrlParser` as deprecated. Just use PHP's `parse_url()` and percent encode your UTF-8.
+- Marked `Guzzle\Common\Collection::inject()` as deprecated.
+- Marked `Guzzle\Plugin\CurlAuth\CurlAuthPlugin` as deprecated. Use
+ `$client->getConfig()->setPath('request.options/auth', array('user', 'pass', 'Basic|Digest|NTLM|Any'));` or
+ `$client->setDefaultOption('auth', array('user', 'pass', 'Basic|Digest|NTLM|Any'));`
+
+3.7 introduces `request.options` as a parameter for a client configuration and as an optional argument to all creational
+request methods. When paired with a client's configuration settings, these options allow you to specify default settings
+for various aspects of a request. Because these options make other previous configuration options redundant, several
+configuration options and methods of a client and AbstractCommand have been deprecated.
+
+- Marked `Guzzle\Service\Client::getDefaultHeaders()` as deprecated. Use `$client->getDefaultOption('headers')`.
+- Marked `Guzzle\Service\Client::setDefaultHeaders()` as deprecated. Use `$client->setDefaultOption('headers/{header_name}', 'value')`.
+- Marked 'request.params' for `Guzzle\Http\Client` as deprecated. Use `$client->setDefaultOption('params/{param_name}', 'value')`
+- Marked 'command.headers', 'command.response_body' and 'command.on_complete' as deprecated for AbstractCommand. These will work through Guzzle 4.0
+
+ $command = $client->getCommand('foo', array(
+ 'command.headers' => array('Test' => '123'),
+ 'command.response_body' => '/path/to/file'
+ ));
+
+ // Should be changed to:
+
+ $command = $client->getCommand('foo', array(
+ 'command.request_options' => array(
+ 'headers' => array('Test' => '123'),
+ 'save_as' => '/path/to/file'
+ )
+ ));
+
+### Interface changes
+
+Additions and changes (you will need to update any implementations or subclasses you may have created):
+
+- Added an `$options` argument to the end of the following methods of `Guzzle\Http\ClientInterface`:
+ createRequest, head, delete, put, patch, post, options, prepareRequest
+- Added an `$options` argument to the end of `Guzzle\Http\Message\Request\RequestFactoryInterface::createRequest()`
+- Added an `applyOptions()` method to `Guzzle\Http\Message\Request\RequestFactoryInterface`
+- Changed `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $body = null)` to
+ `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $options = array())`. You can still pass in a
+ resource, string, or EntityBody into the $options parameter to specify the download location of the response.
+- Changed `Guzzle\Common\Collection::__construct($data)` to no longer accepts a null value for `$data` but a
+ default `array()`
+- Added `Guzzle\Stream\StreamInterface::isRepeatable`
+- Made `Guzzle\Http\Client::expandTemplate` and `getUriTemplate` protected methods.
+
+The following methods were removed from interfaces. All of these methods are still available in the concrete classes
+that implement them, but you should update your code to use alternative methods:
+
+- Removed `Guzzle\Http\ClientInterface::setDefaultHeaders(). Use
+ `$client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`. or
+ `$client->getConfig()->setPath('request.options/headers', array('header_name' => 'value'))` or
+ `$client->setDefaultOption('headers/{header_name}', 'value')`. or
+ `$client->setDefaultOption('headers', array('header_name' => 'value'))`.
+- Removed `Guzzle\Http\ClientInterface::getDefaultHeaders(). Use `$client->getConfig()->getPath('request.options/headers')`.
+- Removed `Guzzle\Http\ClientInterface::expandTemplate()`. This is an implementation detail.
+- Removed `Guzzle\Http\ClientInterface::setRequestFactory()`. This is an implementation detail.
+- Removed `Guzzle\Http\ClientInterface::getCurlMulti()`. This is a very specific implementation detail.
+- Removed `Guzzle\Http\Message\RequestInterface::canCache`. Use the CachePlugin.
+- Removed `Guzzle\Http\Message\RequestInterface::setIsRedirect`. Use the HistoryPlugin.
+- Removed `Guzzle\Http\Message\RequestInterface::isRedirect`. Use the HistoryPlugin.
+
+### Cache plugin breaking changes
+
+- CacheKeyProviderInterface and DefaultCacheKeyProvider are no longer used. All of this logic is handled in a
+ CacheStorageInterface. These two objects and interface will be removed in a future version.
+- Always setting X-cache headers on cached responses
+- Default cache TTLs are now handled by the CacheStorageInterface of a CachePlugin
+- `CacheStorageInterface::cache($key, Response $response, $ttl = null)` has changed to `cache(RequestInterface
+ $request, Response $response);`
+- `CacheStorageInterface::fetch($key)` has changed to `fetch(RequestInterface $request);`
+- `CacheStorageInterface::delete($key)` has changed to `delete(RequestInterface $request);`
+- Added `CacheStorageInterface::purge($url)`
+- `DefaultRevalidation::__construct(CacheKeyProviderInterface $cacheKey, CacheStorageInterface $cache, CachePlugin
+ $plugin)` has changed to `DefaultRevalidation::__construct(CacheStorageInterface $cache,
+ CanCacheStrategyInterface $canCache = null)`
+- Added `RevalidationInterface::shouldRevalidate(RequestInterface $request, Response $response)`
+
+3.5 to 3.6
+----------
+
+* Mixed casing of headers are now forced to be a single consistent casing across all values for that header.
+* Messages internally use a HeaderCollection object to delegate handling case-insensitive header resolution
+* Removed the whole changedHeader() function system of messages because all header changes now go through addHeader().
+ For example, setHeader() first removes the header using unset on a HeaderCollection and then calls addHeader().
+ Keeping the Host header and URL host in sync is now handled by overriding the addHeader method in Request.
+* Specific header implementations can be created for complex headers. When a message creates a header, it uses a
+ HeaderFactory which can map specific headers to specific header classes. There is now a Link header and
+ CacheControl header implementation.
+* Moved getLinks() from Response to just be used on a Link header object.
+
+If you previously relied on Guzzle\Http\Message\Header::raw(), then you will need to update your code to use the
+HeaderInterface (e.g. toArray(), getAll(), etc.).
+
+### Interface changes
+
+* Removed from interface: Guzzle\Http\ClientInterface::setUriTemplate
+* Removed from interface: Guzzle\Http\ClientInterface::setCurlMulti()
+* Removed Guzzle\Http\Message\Request::receivedRequestHeader() and implemented this functionality in
+ Guzzle\Http\Curl\RequestMediator
+* Removed the optional $asString parameter from MessageInterface::getHeader(). Just cast the header to a string.
+* Removed the optional $tryChunkedTransfer option from Guzzle\Http\Message\EntityEnclosingRequestInterface
+* Removed the $asObjects argument from Guzzle\Http\Message\MessageInterface::getHeaders()
+
+### Removed deprecated functions
+
+* Removed Guzzle\Parser\ParserRegister::get(). Use getParser()
+* Removed Guzzle\Parser\ParserRegister::set(). Use registerParser().
+
+### Deprecations
+
+* The ability to case-insensitively search for header values
+* Guzzle\Http\Message\Header::hasExactHeader
+* Guzzle\Http\Message\Header::raw. Use getAll()
+* Deprecated cache control specific methods on Guzzle\Http\Message\AbstractMessage. Use the CacheControl header object
+ instead.
+
+### Other changes
+
+* All response header helper functions return a string rather than mixing Header objects and strings inconsistently
+* Removed cURL blacklist support. This is no longer necessary now that Expect, Accept, etc. are managed by Guzzle
+ directly via interfaces
+* Removed the injecting of a request object onto a response object. The methods to get and set a request still exist
+ but are a no-op until removed.
+* Most classes that used to require a `Guzzle\Service\Command\CommandInterface` typehint now request a
+ `Guzzle\Service\Command\ArrayCommandInterface`.
+* Added `Guzzle\Http\Message\RequestInterface::startResponse()` to the RequestInterface to handle injecting a response
+ on a request while the request is still being transferred
+* `Guzzle\Service\Command\CommandInterface` now extends from ToArrayInterface and ArrayAccess
+
+3.3 to 3.4
+----------
+
+Base URLs of a client now follow the rules of http://tools.ietf.org/html/rfc3986#section-5.2.2 when merging URLs.
+
+3.2 to 3.3
+----------
+
+### Response::getEtag() quote stripping removed
+
+`Guzzle\Http\Message\Response::getEtag()` no longer strips quotes around the ETag response header
+
+### Removed `Guzzle\Http\Utils`
+
+The `Guzzle\Http\Utils` class was removed. This class was only used for testing.
+
+### Stream wrapper and type
+
+`Guzzle\Stream\Stream::getWrapper()` and `Guzzle\Stream\Stream::getStreamType()` are no longer converted to lowercase.
+
+### curl.emit_io became emit_io
+
+Emitting IO events from a RequestMediator is now a parameter that must be set in a request's curl options using the
+'emit_io' key. This was previously set under a request's parameters using 'curl.emit_io'
+
+3.1 to 3.2
+----------
+
+### CurlMulti is no longer reused globally
+
+Before 3.2, the same CurlMulti object was reused globally for each client. This can cause issue where plugins added
+to a single client can pollute requests dispatched from other clients.
+
+If you still wish to reuse the same CurlMulti object with each client, then you can add a listener to the
+ServiceBuilder's `service_builder.create_client` event to inject a custom CurlMulti object into each client as it is
+created.
+
+```php
+$multi = new Guzzle\Http\Curl\CurlMulti();
+$builder = Guzzle\Service\Builder\ServiceBuilder::factory('/path/to/config.json');
+$builder->addListener('service_builder.create_client', function ($event) use ($multi) {
+ $event['client']->setCurlMulti($multi);
+}
+});
+```
+
+### No default path
+
+URLs no longer have a default path value of '/' if no path was specified.
+
+Before:
+
+```php
+$request = $client->get('http://www.foo.com');
+echo $request->getUrl();
+// >> http://www.foo.com/
+```
+
+After:
+
+```php
+$request = $client->get('http://www.foo.com');
+echo $request->getUrl();
+// >> http://www.foo.com
+```
+
+### Less verbose BadResponseException
+
+The exception message for `Guzzle\Http\Exception\BadResponseException` no longer contains the full HTTP request and
+response information. You can, however, get access to the request and response object by calling `getRequest()` or
+`getResponse()` on the exception object.
+
+### Query parameter aggregation
+
+Multi-valued query parameters are no longer aggregated using a callback function. `Guzzle\Http\Query` now has a
+setAggregator() method that accepts a `Guzzle\Http\QueryAggregator\QueryAggregatorInterface` object. This object is
+responsible for handling the aggregation of multi-valued query string variables into a flattened hash.
+
+2.8 to 3.x
+----------
+
+### Guzzle\Service\Inspector
+
+Change `\Guzzle\Service\Inspector::fromConfig` to `\Guzzle\Common\Collection::fromConfig`
+
+**Before**
+
+```php
+use Guzzle\Service\Inspector;
+
+class YourClient extends \Guzzle\Service\Client
+{
+ public static function factory($config = array())
+ {
+ $default = array();
+ $required = array('base_url', 'username', 'api_key');
+ $config = Inspector::fromConfig($config, $default, $required);
+
+ $client = new self(
+ $config->get('base_url'),
+ $config->get('username'),
+ $config->get('api_key')
+ );
+ $client->setConfig($config);
+
+ $client->setDescription(ServiceDescription::factory(__DIR__ . DIRECTORY_SEPARATOR . 'client.json'));
+
+ return $client;
+ }
+```
+
+**After**
+
+```php
+use Guzzle\Common\Collection;
+
+class YourClient extends \Guzzle\Service\Client
+{
+ public static function factory($config = array())
+ {
+ $default = array();
+ $required = array('base_url', 'username', 'api_key');
+ $config = Collection::fromConfig($config, $default, $required);
+
+ $client = new self(
+ $config->get('base_url'),
+ $config->get('username'),
+ $config->get('api_key')
+ );
+ $client->setConfig($config);
+
+ $client->setDescription(ServiceDescription::factory(__DIR__ . DIRECTORY_SEPARATOR . 'client.json'));
+
+ return $client;
+ }
+```
+
+### Convert XML Service Descriptions to JSON
+
+**Before**
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<client>
+ <commands>
+ <!-- Groups -->
+ <command name="list_groups" method="GET" uri="groups.json">
+ <doc>Get a list of groups</doc>
+ </command>
+ <command name="search_groups" method="GET" uri='search.json?query="{{query}} type:group"'>
+ <doc>Uses a search query to get a list of groups</doc>
+ <param name="query" type="string" required="true" />
+ </command>
+ <command name="create_group" method="POST" uri="groups.json">
+ <doc>Create a group</doc>
+ <param name="data" type="array" location="body" filters="json_encode" doc="Group JSON"/>
+ <param name="Content-Type" location="header" static="application/json"/>
+ </command>
+ <command name="delete_group" method="DELETE" uri="groups/{{id}}.json">
+ <doc>Delete a group by ID</doc>
+ <param name="id" type="integer" required="true"/>
+ </command>
+ <command name="get_group" method="GET" uri="groups/{{id}}.json">
+ <param name="id" type="integer" required="true"/>
+ </command>
+ <command name="update_group" method="PUT" uri="groups/{{id}}.json">
+ <doc>Update a group</doc>
+ <param name="id" type="integer" required="true"/>
+ <param name="data" type="array" location="body" filters="json_encode" doc="Group JSON"/>
+ <param name="Content-Type" location="header" static="application/json"/>
+ </command>
+ </commands>
+</client>
+```
+
+**After**
+
+```json
+{
+ "name": "Zendesk REST API v2",
+ "apiVersion": "2012-12-31",
+ "description":"Provides access to Zendesk views, groups, tickets, ticket fields, and users",
+ "operations": {
+ "list_groups": {
+ "httpMethod":"GET",
+ "uri": "groups.json",
+ "summary": "Get a list of groups"
+ },
+ "search_groups":{
+ "httpMethod":"GET",
+ "uri": "search.json?query=\"{query} type:group\"",
+ "summary": "Uses a search query to get a list of groups",
+ "parameters":{
+ "query":{
+ "location": "uri",
+ "description":"Zendesk Search Query",
+ "type": "string",
+ "required": true
+ }
+ }
+ },
+ "create_group": {
+ "httpMethod":"POST",
+ "uri": "groups.json",
+ "summary": "Create a group",
+ "parameters":{
+ "data": {
+ "type": "array",
+ "location": "body",
+ "description":"Group JSON",
+ "filters": "json_encode",
+ "required": true
+ },
+ "Content-Type":{
+ "type": "string",
+ "location":"header",
+ "static": "application/json"
+ }
+ }
+ },
+ "delete_group": {
+ "httpMethod":"DELETE",
+ "uri": "groups/{id}.json",
+ "summary": "Delete a group",
+ "parameters":{
+ "id":{
+ "location": "uri",
+ "description":"Group to delete by ID",
+ "type": "integer",
+ "required": true
+ }
+ }
+ },
+ "get_group": {
+ "httpMethod":"GET",
+ "uri": "groups/{id}.json",
+ "summary": "Get a ticket",
+ "parameters":{
+ "id":{
+ "location": "uri",
+ "description":"Group to get by ID",
+ "type": "integer",
+ "required": true
+ }
+ }
+ },
+ "update_group": {
+ "httpMethod":"PUT",
+ "uri": "groups/{id}.json",
+ "summary": "Update a group",
+ "parameters":{
+ "id": {
+ "location": "uri",
+ "description":"Group to update by ID",
+ "type": "integer",
+ "required": true
+ },
+ "data": {
+ "type": "array",
+ "location": "body",
+ "description":"Group JSON",
+ "filters": "json_encode",
+ "required": true
+ },
+ "Content-Type":{
+ "type": "string",
+ "location":"header",
+ "static": "application/json"
+ }
+ }
+ }
+}
+```
+
+### Guzzle\Service\Description\ServiceDescription
+
+Commands are now called Operations
+
+**Before**
+
+```php
+use Guzzle\Service\Description\ServiceDescription;
+
+$sd = new ServiceDescription();
+$sd->getCommands(); // @returns ApiCommandInterface[]
+$sd->hasCommand($name);
+$sd->getCommand($name); // @returns ApiCommandInterface|null
+$sd->addCommand($command); // @param ApiCommandInterface $command
+```
+
+**After**
+
+```php
+use Guzzle\Service\Description\ServiceDescription;
+
+$sd = new ServiceDescription();
+$sd->getOperations(); // @returns OperationInterface[]
+$sd->hasOperation($name);
+$sd->getOperation($name); // @returns OperationInterface|null
+$sd->addOperation($operation); // @param OperationInterface $operation
+```
+
+### Guzzle\Common\Inflection\Inflector
+
+Namespace is now `Guzzle\Inflection\Inflector`
+
+### Guzzle\Http\Plugin
+
+Namespace is now `Guzzle\Plugin`. Many other changes occur within this namespace and are detailed in their own sections below.
+
+### Guzzle\Http\Plugin\LogPlugin and Guzzle\Common\Log
+
+Now `Guzzle\Plugin\Log\LogPlugin` and `Guzzle\Log` respectively.
+
+**Before**
+
+```php
+use Guzzle\Common\Log\ClosureLogAdapter;
+use Guzzle\Http\Plugin\LogPlugin;
+
+/** @var \Guzzle\Http\Client */
+$client;
+
+// $verbosity is an integer indicating desired message verbosity level
+$client->addSubscriber(new LogPlugin(new ClosureLogAdapter(function($m) { echo $m; }, $verbosity = LogPlugin::LOG_VERBOSE);
+```
+
+**After**
+
+```php
+use Guzzle\Log\ClosureLogAdapter;
+use Guzzle\Log\MessageFormatter;
+use Guzzle\Plugin\Log\LogPlugin;
+
+/** @var \Guzzle\Http\Client */
+$client;
+
+// $format is a string indicating desired message format -- @see MessageFormatter
+$client->addSubscriber(new LogPlugin(new ClosureLogAdapter(function($m) { echo $m; }, $format = MessageFormatter::DEBUG_FORMAT);
+```
+
+### Guzzle\Http\Plugin\CurlAuthPlugin
+
+Now `Guzzle\Plugin\CurlAuth\CurlAuthPlugin`.
+
+### Guzzle\Http\Plugin\ExponentialBackoffPlugin
+
+Now `Guzzle\Plugin\Backoff\BackoffPlugin`, and other changes.
+
+**Before**
+
+```php
+use Guzzle\Http\Plugin\ExponentialBackoffPlugin;
+
+$backoffPlugin = new ExponentialBackoffPlugin($maxRetries, array_merge(
+ ExponentialBackoffPlugin::getDefaultFailureCodes(), array(429)
+ ));
+
+$client->addSubscriber($backoffPlugin);
+```
+
+**After**
+
+```php
+use Guzzle\Plugin\Backoff\BackoffPlugin;
+use Guzzle\Plugin\Backoff\HttpBackoffStrategy;
+
+// Use convenient factory method instead -- see implementation for ideas of what
+// you can do with chaining backoff strategies
+$backoffPlugin = BackoffPlugin::getExponentialBackoff($maxRetries, array_merge(
+ HttpBackoffStrategy::getDefaultFailureCodes(), array(429)
+ ));
+$client->addSubscriber($backoffPlugin);
+```
+
+### Known Issues
+
+#### [BUG] Accept-Encoding header behavior changed unintentionally.
+
+(See #217) (Fixed in 09daeb8c666fb44499a0646d655a8ae36456575e)
+
+In version 2.8 setting the `Accept-Encoding` header would set the CURLOPT_ENCODING option, which permitted cURL to
+properly handle gzip/deflate compressed responses from the server. In versions affected by this bug this does not happen.
+See issue #217 for a workaround, or use a version containing the fix.
diff --git a/server/vendor/guzzlehttp/guzzle/composer.json b/server/vendor/guzzlehttp/guzzle/composer.json
new file mode 100644
index 0000000..1f8b070
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/composer.json
@@ -0,0 +1,41 @@
+{
+ "name": "guzzlehttp/guzzle",
+ "type": "library",
+ "description": "Guzzle is a PHP HTTP client library",
+ "keywords": ["framework", "http", "rest", "web service", "curl", "client", "HTTP client"],
+ "homepage": "http://guzzlephp.org/",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "require": {
+ "php": ">=5.5.0",
+ "guzzlehttp/psr7": "~1.1",
+ "guzzlehttp/promises": "~1.0"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "phpunit/phpunit": "~4.0",
+ "psr/log": "~1.0"
+ },
+ "autoload": {
+ "files": ["src/functions_include.php"],
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "GuzzleHttp\\Tests\\": "tests/"
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "6.1-dev"
+ }
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Client.php b/server/vendor/guzzlehttp/guzzle/src/Client.php
new file mode 100644
index 0000000..2e86ece
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Client.php
@@ -0,0 +1,397 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Cookie\CookieJar;
+use GuzzleHttp\Promise;
+use GuzzleHttp\Psr7;
+use Psr\Http\Message\UriInterface;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * @method ResponseInterface get($uri, array $options = [])
+ * @method ResponseInterface head($uri, array $options = [])
+ * @method ResponseInterface put($uri, array $options = [])
+ * @method ResponseInterface post($uri, array $options = [])
+ * @method ResponseInterface patch($uri, array $options = [])
+ * @method ResponseInterface delete($uri, array $options = [])
+ * @method Promise\PromiseInterface getAsync($uri, array $options = [])
+ * @method Promise\PromiseInterface headAsync($uri, array $options = [])
+ * @method Promise\PromiseInterface putAsync($uri, array $options = [])
+ * @method Promise\PromiseInterface postAsync($uri, array $options = [])
+ * @method Promise\PromiseInterface patchAsync($uri, array $options = [])
+ * @method Promise\PromiseInterface deleteAsync($uri, array $options = [])
+ */
+class Client implements ClientInterface
+{
+ /** @var array Default request options */
+ private $config;
+
+ /**
+ * Clients accept an array of constructor parameters.
+ *
+ * Here's an example of creating a client using a base_uri and an array of
+ * default request options to apply to each request:
+ *
+ * $client = new Client([
+ * 'base_uri' => 'http://www.foo.com/1.0/',
+ * 'timeout' => 0,
+ * 'allow_redirects' => false,
+ * 'proxy' => '192.168.16.1:10'
+ * ]);
+ *
+ * Client configuration settings include the following options:
+ *
+ * - handler: (callable) Function that transfers HTTP requests over the
+ * wire. The function is called with a Psr7\Http\Message\RequestInterface
+ * and array of transfer options, and must return a
+ * GuzzleHttp\Promise\PromiseInterface that is fulfilled with a
+ * Psr7\Http\Message\ResponseInterface on success. "handler" is a
+ * constructor only option that cannot be overridden in per/request
+ * options. If no handler is provided, a default handler will be created
+ * that enables all of the request options below by attaching all of the
+ * default middleware to the handler.
+ * - base_uri: (string|UriInterface) Base URI of the client that is merged
+ * into relative URIs. Can be a string or instance of UriInterface.
+ * - **: any request option
+ *
+ * @param array $config Client configuration settings.
+ *
+ * @see \GuzzleHttp\RequestOptions for a list of available request options.
+ */
+ public function __construct(array $config = [])
+ {
+ if (!isset($config['handler'])) {
+ $config['handler'] = HandlerStack::create();
+ }
+
+ // Convert the base_uri to a UriInterface
+ if (isset($config['base_uri'])) {
+ $config['base_uri'] = Psr7\uri_for($config['base_uri']);
+ }
+
+ $this->configureDefaults($config);
+ }
+
+ public function __call($method, $args)
+ {
+ if (count($args) < 1) {
+ throw new \InvalidArgumentException('Magic request methods require a URI and optional options array');
+ }
+
+ $uri = $args[0];
+ $opts = isset($args[1]) ? $args[1] : [];
+
+ return substr($method, -5) === 'Async'
+ ? $this->requestAsync(substr($method, 0, -5), $uri, $opts)
+ : $this->request($method, $uri, $opts);
+ }
+
+ public function sendAsync(RequestInterface $request, array $options = [])
+ {
+ // Merge the base URI into the request URI if needed.
+ $options = $this->prepareDefaults($options);
+
+ return $this->transfer(
+ $request->withUri($this->buildUri($request->getUri(), $options)),
+ $options
+ );
+ }
+
+ public function send(RequestInterface $request, array $options = [])
+ {
+ $options[RequestOptions::SYNCHRONOUS] = true;
+ return $this->sendAsync($request, $options)->wait();
+ }
+
+ public function requestAsync($method, $uri = null, array $options = [])
+ {
+ $options = $this->prepareDefaults($options);
+ // Remove request modifying parameter because it can be done up-front.
+ $headers = isset($options['headers']) ? $options['headers'] : [];
+ $body = isset($options['body']) ? $options['body'] : null;
+ $version = isset($options['version']) ? $options['version'] : '1.1';
+ // Merge the URI into the base URI.
+ $uri = $this->buildUri($uri, $options);
+ if (is_array($body)) {
+ $this->invalidBody();
+ }
+ $request = new Psr7\Request($method, $uri, $headers, $body, $version);
+ // Remove the option so that they are not doubly-applied.
+ unset($options['headers'], $options['body'], $options['version']);
+
+ return $this->transfer($request, $options);
+ }
+
+ public function request($method, $uri = null, array $options = [])
+ {
+ $options[RequestOptions::SYNCHRONOUS] = true;
+ return $this->requestAsync($method, $uri, $options)->wait();
+ }
+
+ public function getConfig($option = null)
+ {
+ return $option === null
+ ? $this->config
+ : (isset($this->config[$option]) ? $this->config[$option] : null);
+ }
+
+ private function buildUri($uri, array $config)
+ {
+ if (!isset($config['base_uri'])) {
+ return $uri instanceof UriInterface ? $uri : new Psr7\Uri($uri);
+ }
+
+ return Psr7\Uri::resolve(Psr7\uri_for($config['base_uri']), $uri);
+ }
+
+ /**
+ * Configures the default options for a client.
+ *
+ * @param array $config
+ */
+ private function configureDefaults(array $config)
+ {
+ $defaults = [
+ 'allow_redirects' => RedirectMiddleware::$defaultSettings,
+ 'http_errors' => true,
+ 'decode_content' => true,
+ 'verify' => true,
+ 'cookies' => false
+ ];
+
+ // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set
+ if ($proxy = getenv('HTTP_PROXY')) {
+ $defaults['proxy']['http'] = $proxy;
+ }
+
+ if ($proxy = getenv('HTTPS_PROXY')) {
+ $defaults['proxy']['https'] = $proxy;
+ }
+
+ if ($noProxy = getenv('NO_PROXY')) {
+ $cleanedNoProxy = str_replace(' ', '', $noProxy);
+ $defaults['proxy']['no'] = explode(',', $cleanedNoProxy);
+ }
+
+ $this->config = $config + $defaults;
+
+ if (!empty($config['cookies']) && $config['cookies'] === true) {
+ $this->config['cookies'] = new CookieJar();
+ }
+
+ // Add the default user-agent header.
+ if (!isset($this->config['headers'])) {
+ $this->config['headers'] = ['User-Agent' => default_user_agent()];
+ } else {
+ // Add the User-Agent header if one was not already set.
+ foreach (array_keys($this->config['headers']) as $name) {
+ if (strtolower($name) === 'user-agent') {
+ return;
+ }
+ }
+ $this->config['headers']['User-Agent'] = default_user_agent();
+ }
+ }
+
+ /**
+ * Merges default options into the array.
+ *
+ * @param array $options Options to modify by reference
+ *
+ * @return array
+ */
+ private function prepareDefaults($options)
+ {
+ $defaults = $this->config;
+
+ if (!empty($defaults['headers'])) {
+ // Default headers are only added if they are not present.
+ $defaults['_conditional'] = $defaults['headers'];
+ unset($defaults['headers']);
+ }
+
+ // Special handling for headers is required as they are added as
+ // conditional headers and as headers passed to a request ctor.
+ if (array_key_exists('headers', $options)) {
+ // Allows default headers to be unset.
+ if ($options['headers'] === null) {
+ $defaults['_conditional'] = null;
+ unset($options['headers']);
+ } elseif (!is_array($options['headers'])) {
+ throw new \InvalidArgumentException('headers must be an array');
+ }
+ }
+
+ // Shallow merge defaults underneath options.
+ $result = $options + $defaults;
+
+ // Remove null values.
+ foreach ($result as $k => $v) {
+ if ($v === null) {
+ unset($result[$k]);
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Transfers the given request and applies request options.
+ *
+ * The URI of the request is not modified and the request options are used
+ * as-is without merging in default options.
+ *
+ * @param RequestInterface $request
+ * @param array $options
+ *
+ * @return Promise\PromiseInterface
+ */
+ private function transfer(RequestInterface $request, array $options)
+ {
+ // save_to -> sink
+ if (isset($options['save_to'])) {
+ $options['sink'] = $options['save_to'];
+ unset($options['save_to']);
+ }
+
+ // exceptions -> http_error
+ if (isset($options['exceptions'])) {
+ $options['http_errors'] = $options['exceptions'];
+ unset($options['exceptions']);
+ }
+
+ $request = $this->applyOptions($request, $options);
+ $handler = $options['handler'];
+
+ try {
+ return Promise\promise_for($handler($request, $options));
+ } catch (\Exception $e) {
+ return Promise\rejection_for($e);
+ }
+ }
+
+ /**
+ * Applies the array of request options to a request.
+ *
+ * @param RequestInterface $request
+ * @param array $options
+ *
+ * @return RequestInterface
+ */
+ private function applyOptions(RequestInterface $request, array &$options)
+ {
+ $modify = [];
+
+ if (isset($options['form_params'])) {
+ if (isset($options['multipart'])) {
+ throw new \InvalidArgumentException('You cannot use '
+ . 'form_params and multipart at the same time. Use the '
+ . 'form_params option if you want to send application/'
+ . 'x-www-form-urlencoded requests, and the multipart '
+ . 'option to send multipart/form-data requests.');
+ }
+ $options['body'] = http_build_query($options['form_params'], null, '&');
+ unset($options['form_params']);
+ $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
+ }
+
+ if (isset($options['multipart'])) {
+ $elements = $options['multipart'];
+ unset($options['multipart']);
+ $options['body'] = new Psr7\MultipartStream($elements);
+ }
+
+ if (!empty($options['decode_content'])
+ && $options['decode_content'] !== true
+ ) {
+ $modify['set_headers']['Accept-Encoding'] = $options['decode_content'];
+ }
+
+ if (isset($options['headers'])) {
+ if (isset($modify['set_headers'])) {
+ $modify['set_headers'] = $options['headers'] + $modify['set_headers'];
+ } else {
+ $modify['set_headers'] = $options['headers'];
+ }
+ unset($options['headers']);
+ }
+
+ if (isset($options['body'])) {
+ if (is_array($options['body'])) {
+ $this->invalidBody();
+ }
+ $modify['body'] = Psr7\stream_for($options['body']);
+ unset($options['body']);
+ }
+
+ if (!empty($options['auth'])) {
+ $value = $options['auth'];
+ $type = is_array($value)
+ ? (isset($value[2]) ? strtolower($value[2]) : 'basic')
+ : $value;
+ $config['auth'] = $value;
+ switch (strtolower($type)) {
+ case 'basic':
+ $modify['set_headers']['Authorization'] = 'Basic '
+ . base64_encode("$value[0]:$value[1]");
+ break;
+ case 'digest':
+ // @todo: Do not rely on curl
+ $options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_DIGEST;
+ $options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
+ break;
+ }
+ }
+
+ if (isset($options['query'])) {
+ $value = $options['query'];
+ if (is_array($value)) {
+ $value = http_build_query($value, null, '&', PHP_QUERY_RFC3986);
+ }
+ if (!is_string($value)) {
+ throw new \InvalidArgumentException('query must be a string or array');
+ }
+ $modify['query'] = $value;
+ unset($options['query']);
+ }
+
+ if (isset($options['json'])) {
+ $modify['body'] = Psr7\stream_for(json_encode($options['json']));
+ $options['_conditional']['Content-Type'] = 'application/json';
+ unset($options['json']);
+ }
+
+ $request = Psr7\modify_request($request, $modify);
+ if ($request->getBody() instanceof Psr7\MultipartStream) {
+ // Use a multipart/form-data POST if a Content-Type is not set.
+ $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='
+ . $request->getBody()->getBoundary();
+ }
+
+ // Merge in conditional headers if they are not present.
+ if (isset($options['_conditional'])) {
+ // Build up the changes so it's in a single clone of the message.
+ $modify = [];
+ foreach ($options['_conditional'] as $k => $v) {
+ if (!$request->hasHeader($k)) {
+ $modify['set_headers'][$k] = $v;
+ }
+ }
+ $request = Psr7\modify_request($request, $modify);
+ // Don't pass this internal value along to middleware/handlers.
+ unset($options['_conditional']);
+ }
+
+ return $request;
+ }
+
+ private function invalidBody()
+ {
+ throw new \InvalidArgumentException('Passing in the "body" request '
+ . 'option as an array to send a POST request has been deprecated. '
+ . 'Please use the "form_params" request option to send a '
+ . 'application/x-www-form-urlencoded request, or a the "multipart" '
+ . 'request option to send a multipart/form-data request.');
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/ClientInterface.php b/server/vendor/guzzlehttp/guzzle/src/ClientInterface.php
new file mode 100644
index 0000000..19068e1
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/ClientInterface.php
@@ -0,0 +1,84 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Promise\PromiseInterface;
+use GuzzleHttp\Exception\GuzzleException;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\UriInterface;
+
+/**
+ * Client interface for sending HTTP requests.
+ */
+interface ClientInterface
+{
+ const VERSION = '6.1.1';
+
+ /**
+ * Send an HTTP request.
+ *
+ * @param RequestInterface $request Request to send
+ * @param array $options Request options to apply to the given
+ * request and to the transfer.
+ *
+ * @return ResponseInterface
+ * @throws GuzzleException
+ */
+ public function send(RequestInterface $request, array $options = []);
+
+ /**
+ * Asynchronously send an HTTP request.
+ *
+ * @param RequestInterface $request Request to send
+ * @param array $options Request options to apply to the given
+ * request and to the transfer.
+ *
+ * @return PromiseInterface
+ */
+ public function sendAsync(RequestInterface $request, array $options = []);
+
+ /**
+ * Create and send an HTTP request.
+ *
+ * Use an absolute path to override the base path of the client, or a
+ * relative path to append to the base path of the client. The URL can
+ * contain the query string as well.
+ *
+ * @param string $method HTTP method
+ * @param string|UriInterface $uri URI object or string.
+ * @param array $options Request options to apply.
+ *
+ * @return ResponseInterface
+ * @throws GuzzleException
+ */
+ public function request($method, $uri, array $options = []);
+
+ /**
+ * Create and send an asynchronous HTTP request.
+ *
+ * Use an absolute path to override the base path of the client, or a
+ * relative path to append to the base path of the client. The URL can
+ * contain the query string as well. Use an array to provide a URL
+ * template and additional variables to use in the URL template expansion.
+ *
+ * @param string $method HTTP method
+ * @param string|UriInterface $uri URI object or string.
+ * @param array $options Request options to apply.
+ *
+ * @return PromiseInterface
+ */
+ public function requestAsync($method, $uri, array $options = []);
+
+ /**
+ * Get a client configuration option.
+ *
+ * These options include default request options of the client, a "handler"
+ * (if utilized by the concrete client), and a "base_uri" if utilized by
+ * the concrete client.
+ *
+ * @param string|null $option The config option to retrieve.
+ *
+ * @return mixed
+ */
+ public function getConfig($option = null);
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php b/server/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php
new file mode 100644
index 0000000..11421fe
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php
@@ -0,0 +1,277 @@
+<?php
+namespace GuzzleHttp\Cookie;
+
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Cookie jar that stores cookies an an array
+ */
+class CookieJar implements CookieJarInterface
+{
+ /** @var SetCookie[] Loaded cookie data */
+ private $cookies = [];
+
+ /** @var bool */
+ private $strictMode;
+
+ /**
+ * @param bool $strictMode Set to true to throw exceptions when invalid
+ * cookies are added to the cookie jar.
+ * @param array $cookieArray Array of SetCookie objects or a hash of
+ * arrays that can be used with the SetCookie
+ * constructor
+ */
+ public function __construct($strictMode = false, $cookieArray = [])
+ {
+ $this->strictMode = $strictMode;
+
+ foreach ($cookieArray as $cookie) {
+ if (!($cookie instanceof SetCookie)) {
+ $cookie = new SetCookie($cookie);
+ }
+ $this->setCookie($cookie);
+ }
+ }
+
+ /**
+ * Create a new Cookie jar from an associative array and domain.
+ *
+ * @param array $cookies Cookies to create the jar from
+ * @param string $domain Domain to set the cookies to
+ *
+ * @return self
+ */
+ public static function fromArray(array $cookies, $domain)
+ {
+ $cookieJar = new self();
+ foreach ($cookies as $name => $value) {
+ $cookieJar->setCookie(new SetCookie([
+ 'Domain' => $domain,
+ 'Name' => $name,
+ 'Value' => $value,
+ 'Discard' => true
+ ]));
+ }
+
+ return $cookieJar;
+ }
+
+ /**
+ * Quote the cookie value if it is not already quoted and it contains
+ * problematic characters.
+ *
+ * @param string $value Value that may or may not need to be quoted
+ *
+ * @return string
+ */
+ public static function getCookieValue($value)
+ {
+ if (substr($value, 0, 1) !== '"' &&
+ substr($value, -1, 1) !== '"' &&
+ strpbrk($value, ';,=')
+ ) {
+ $value = '"' . $value . '"';
+ }
+
+ return $value;
+ }
+
+ /**
+ * Evaluate if this cookie should be persisted to storage
+ * that survives between requests.
+ *
+ * @param SetCookie $cookie Being evaluated.
+ * @param bool $allowSessionCookies If we should persist session cookies
+ * @return bool
+ */
+ public static function shouldPersist(
+ SetCookie $cookie,
+ $allowSessionCookies = false
+ ) {
+ if ($cookie->getExpires() || $allowSessionCookies) {
+ if (!$cookie->getDiscard()) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public function toArray()
+ {
+ return array_map(function (SetCookie $cookie) {
+ return $cookie->toArray();
+ }, $this->getIterator()->getArrayCopy());
+ }
+
+ public function clear($domain = null, $path = null, $name = null)
+ {
+ if (!$domain) {
+ $this->cookies = [];
+ return;
+ } elseif (!$path) {
+ $this->cookies = array_filter(
+ $this->cookies,
+ function (SetCookie $cookie) use ($path, $domain) {
+ return !$cookie->matchesDomain($domain);
+ }
+ );
+ } elseif (!$name) {
+ $this->cookies = array_filter(
+ $this->cookies,
+ function (SetCookie $cookie) use ($path, $domain) {
+ return !($cookie->matchesPath($path) &&
+ $cookie->matchesDomain($domain));
+ }
+ );
+ } else {
+ $this->cookies = array_filter(
+ $this->cookies,
+ function (SetCookie $cookie) use ($path, $domain, $name) {
+ return !($cookie->getName() == $name &&
+ $cookie->matchesPath($path) &&
+ $cookie->matchesDomain($domain));
+ }
+ );
+ }
+ }
+
+ public function clearSessionCookies()
+ {
+ $this->cookies = array_filter(
+ $this->cookies,
+ function (SetCookie $cookie) {
+ return !$cookie->getDiscard() && $cookie->getExpires();
+ }
+ );
+ }
+
+ public function setCookie(SetCookie $cookie)
+ {
+ // If the name string is empty (but not 0), ignore the set-cookie
+ // string entirely.
+ $name = $cookie->getName();
+ if (!$name && $name !== '0') {
+ return false;
+ }
+
+ // Only allow cookies with set and valid domain, name, value
+ $result = $cookie->validate();
+ if ($result !== true) {
+ if ($this->strictMode) {
+ throw new \RuntimeException('Invalid cookie: ' . $result);
+ } else {
+ $this->removeCookieIfEmpty($cookie);
+ return false;
+ }
+ }
+
+ // Resolve conflicts with previously set cookies
+ foreach ($this->cookies as $i => $c) {
+
+ // Two cookies are identical, when their path, and domain are
+ // identical.
+ if ($c->getPath() != $cookie->getPath() ||
+ $c->getDomain() != $cookie->getDomain() ||
+ $c->getName() != $cookie->getName()
+ ) {
+ continue;
+ }
+
+ // The previously set cookie is a discard cookie and this one is
+ // not so allow the new cookie to be set
+ if (!$cookie->getDiscard() && $c->getDiscard()) {
+ unset($this->cookies[$i]);
+ continue;
+ }
+
+ // If the new cookie's expiration is further into the future, then
+ // replace the old cookie
+ if ($cookie->getExpires() > $c->getExpires()) {
+ unset($this->cookies[$i]);
+ continue;
+ }
+
+ // If the value has changed, we better change it
+ if ($cookie->getValue() !== $c->getValue()) {
+ unset($this->cookies[$i]);
+ continue;
+ }
+
+ // The cookie exists, so no need to continue
+ return false;
+ }
+
+ $this->cookies[] = $cookie;
+
+ return true;
+ }
+
+ public function count()
+ {
+ return count($this->cookies);
+ }
+
+ public function getIterator()
+ {
+ return new \ArrayIterator(array_values($this->cookies));
+ }
+
+ public function extractCookies(
+ RequestInterface $request,
+ ResponseInterface $response
+ ) {
+ if ($cookieHeader = $response->getHeader('Set-Cookie')) {
+ foreach ($cookieHeader as $cookie) {
+ $sc = SetCookie::fromString($cookie);
+ if (!$sc->getDomain()) {
+ $sc->setDomain($request->getUri()->getHost());
+ }
+ $this->setCookie($sc);
+ }
+ }
+ }
+
+ public function withCookieHeader(RequestInterface $request)
+ {
+ $values = [];
+ $uri = $request->getUri();
+ $scheme = $uri->getScheme();
+ $host = $uri->getHost();
+ $path = $uri->getPath() ?: '/';
+
+ foreach ($this->cookies as $cookie) {
+ if ($cookie->matchesPath($path) &&
+ $cookie->matchesDomain($host) &&
+ !$cookie->isExpired() &&
+ (!$cookie->getSecure() || $scheme == 'https')
+ ) {
+ $values[] = $cookie->getName() . '='
+ . self::getCookieValue($cookie->getValue());
+ }
+ }
+
+ return $values
+ ? $request->withHeader('Cookie', implode('; ', $values))
+ : $request;
+ }
+
+ /**
+ * If a cookie already exists and the server asks to set it again with a
+ * null value, the cookie must be deleted.
+ *
+ * @param SetCookie $cookie
+ */
+ private function removeCookieIfEmpty(SetCookie $cookie)
+ {
+ $cookieValue = $cookie->getValue();
+ if ($cookieValue === null || $cookieValue === '') {
+ $this->clear(
+ $cookie->getDomain(),
+ $cookie->getPath(),
+ $cookie->getName()
+ );
+ }
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php b/server/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php
new file mode 100644
index 0000000..2cf298a
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php
@@ -0,0 +1,84 @@
+<?php
+namespace GuzzleHttp\Cookie;
+
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Stores HTTP cookies.
+ *
+ * It extracts cookies from HTTP requests, and returns them in HTTP responses.
+ * CookieJarInterface instances automatically expire contained cookies when
+ * necessary. Subclasses are also responsible for storing and retrieving
+ * cookies from a file, database, etc.
+ *
+ * @link http://docs.python.org/2/library/cookielib.html Inspiration
+ */
+interface CookieJarInterface extends \Countable, \IteratorAggregate
+{
+ /**
+ * Create a request with added cookie headers.
+ *
+ * If no matching cookies are found in the cookie jar, then no Cookie
+ * header is added to the request and the same request is returned.
+ *
+ * @param RequestInterface $request Request object to modify.
+ *
+ * @return RequestInterface returns the modified request.
+ */
+ public function withCookieHeader(RequestInterface $request);
+
+ /**
+ * Extract cookies from an HTTP response and store them in the CookieJar.
+ *
+ * @param RequestInterface $request Request that was sent
+ * @param ResponseInterface $response Response that was received
+ */
+ public function extractCookies(
+ RequestInterface $request,
+ ResponseInterface $response
+ );
+
+ /**
+ * Sets a cookie in the cookie jar.
+ *
+ * @param SetCookie $cookie Cookie to set.
+ *
+ * @return bool Returns true on success or false on failure
+ */
+ public function setCookie(SetCookie $cookie);
+
+ /**
+ * Remove cookies currently held in the cookie jar.
+ *
+ * Invoking this method without arguments will empty the whole cookie jar.
+ * If given a $domain argument only cookies belonging to that domain will
+ * be removed. If given a $domain and $path argument, cookies belonging to
+ * the specified path within that domain are removed. If given all three
+ * arguments, then the cookie with the specified name, path and domain is
+ * removed.
+ *
+ * @param string $domain Clears cookies matching a domain
+ * @param string $path Clears cookies matching a domain and path
+ * @param string $name Clears cookies matching a domain, path, and name
+ *
+ * @return CookieJarInterface
+ */
+ public function clear($domain = null, $path = null, $name = null);
+
+ /**
+ * Discard all sessions cookies.
+ *
+ * Removes cookies that don't have an expire field or a have a discard
+ * field set to true. To be called when the user agent shuts down according
+ * to RFC 2965.
+ */
+ public function clearSessionCookies();
+
+ /**
+ * Converts the cookie jar to an array.
+ *
+ * @return array
+ */
+ public function toArray();
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php b/server/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php
new file mode 100644
index 0000000..e4e6248
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php
@@ -0,0 +1,87 @@
+<?php
+namespace GuzzleHttp\Cookie;
+
+/**
+ * Persists non-session cookies using a JSON formatted file
+ */
+class FileCookieJar extends CookieJar
+{
+ /** @var string filename */
+ private $filename;
+
+ /** @var bool Control whether to persist session cookies or not. */
+ private $storeSessionCookies;
+
+ /**
+ * Create a new FileCookieJar object
+ *
+ * @param string $cookieFile File to store the cookie data
+ * @param bool $storeSessionCookies Set to true to store session cookies
+ * in the cookie jar.
+ *
+ * @throws \RuntimeException if the file cannot be found or created
+ */
+ public function __construct($cookieFile, $storeSessionCookies = false)
+ {
+ $this->filename = $cookieFile;
+ $this->storeSessionCookies = $storeSessionCookies;
+
+ if (file_exists($cookieFile)) {
+ $this->load($cookieFile);
+ }
+ }
+
+ /**
+ * Saves the file when shutting down
+ */
+ public function __destruct()
+ {
+ $this->save($this->filename);
+ }
+
+ /**
+ * Saves the cookies to a file.
+ *
+ * @param string $filename File to save
+ * @throws \RuntimeException if the file cannot be found or created
+ */
+ public function save($filename)
+ {
+ $json = [];
+ foreach ($this as $cookie) {
+ /** @var SetCookie $cookie */
+ if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
+ $json[] = $cookie->toArray();
+ }
+ }
+
+ if (false === file_put_contents($filename, json_encode($json))) {
+ throw new \RuntimeException("Unable to save file {$filename}");
+ }
+ }
+
+ /**
+ * Load cookies from a JSON formatted file.
+ *
+ * Old cookies are kept unless overwritten by newly loaded ones.
+ *
+ * @param string $filename Cookie file to load.
+ * @throws \RuntimeException if the file cannot be loaded.
+ */
+ public function load($filename)
+ {
+ $json = file_get_contents($filename);
+ if (false === $json) {
+ throw new \RuntimeException("Unable to load file {$filename}");
+ }
+
+ $data = json_decode($json, true);
+ if (is_array($data)) {
+ foreach (json_decode($json, true) as $cookie) {
+ $this->setCookie(new SetCookie($cookie));
+ }
+ } elseif (strlen($data)) {
+ throw new \RuntimeException("Invalid cookie file: {$filename}");
+ }
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php b/server/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php
new file mode 100644
index 0000000..9cd5f9e
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php
@@ -0,0 +1,72 @@
+<?php
+namespace GuzzleHttp\Cookie;
+
+/**
+ * Persists cookies in the client session
+ */
+class SessionCookieJar extends CookieJar
+{
+ /** @var string session key */
+ private $sessionKey;
+
+ /** @var bool Control whether to persist session cookies or not. */
+ private $storeSessionCookies;
+
+ /**
+ * Create a new SessionCookieJar object
+ *
+ * @param string $sessionKey Session key name to store the cookie
+ * data in session
+ * @param bool $storeSessionCookies Set to true to store session cookies
+ * in the cookie jar.
+ */
+ public function __construct($sessionKey, $storeSessionCookies = false)
+ {
+ $this->sessionKey = $sessionKey;
+ $this->storeSessionCookies = $storeSessionCookies;
+ $this->load();
+ }
+
+ /**
+ * Saves cookies to session when shutting down
+ */
+ public function __destruct()
+ {
+ $this->save();
+ }
+
+ /**
+ * Save cookies to the client session
+ */
+ public function save()
+ {
+ $json = [];
+ foreach ($this as $cookie) {
+ /** @var SetCookie $cookie */
+ if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
+ $json[] = $cookie->toArray();
+ }
+ }
+
+ $_SESSION[$this->sessionKey] = json_encode($json);
+ }
+
+ /**
+ * Load the contents of the client session into the data array
+ */
+ protected function load()
+ {
+ $cookieJar = isset($_SESSION[$this->sessionKey])
+ ? $_SESSION[$this->sessionKey]
+ : null;
+
+ $data = json_decode($cookieJar, true);
+ if (is_array($data)) {
+ foreach ($data as $cookie) {
+ $this->setCookie(new SetCookie($cookie));
+ }
+ } elseif (strlen($data)) {
+ throw new \RuntimeException("Invalid cookie data");
+ }
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php b/server/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php
new file mode 100644
index 0000000..acd654d
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php
@@ -0,0 +1,404 @@
+<?php
+namespace GuzzleHttp\Cookie;
+
+/**
+ * Set-Cookie object
+ */
+class SetCookie
+{
+ /** @var array */
+ private static $defaults = [
+ 'Name' => null,
+ 'Value' => null,
+ 'Domain' => null,
+ 'Path' => '/',
+ 'Max-Age' => null,
+ 'Expires' => null,
+ 'Secure' => false,
+ 'Discard' => false,
+ 'HttpOnly' => false
+ ];
+
+ /** @var array Cookie data */
+ private $data;
+
+ /**
+ * Create a new SetCookie object from a string
+ *
+ * @param string $cookie Set-Cookie header string
+ *
+ * @return self
+ */
+ public static function fromString($cookie)
+ {
+ // Create the default return array
+ $data = self::$defaults;
+ // Explode the cookie string using a series of semicolons
+ $pieces = array_filter(array_map('trim', explode(';', $cookie)));
+ // The name of the cookie (first kvp) must include an equal sign.
+ if (empty($pieces) || !strpos($pieces[0], '=')) {
+ return new self($data);
+ }
+
+ // Add the cookie pieces into the parsed data array
+ foreach ($pieces as $part) {
+
+ $cookieParts = explode('=', $part, 2);
+ $key = trim($cookieParts[0]);
+ $value = isset($cookieParts[1])
+ ? trim($cookieParts[1], " \n\r\t\0\x0B")
+ : true;
+
+ // Only check for non-cookies when cookies have been found
+ if (empty($data['Name'])) {
+ $data['Name'] = $key;
+ $data['Value'] = $value;
+ } else {
+ foreach (array_keys(self::$defaults) as $search) {
+ if (!strcasecmp($search, $key)) {
+ $data[$search] = $value;
+ continue 2;
+ }
+ }
+ $data[$key] = $value;
+ }
+ }
+
+ return new self($data);
+ }
+
+ /**
+ * @param array $data Array of cookie data provided by a Cookie parser
+ */
+ public function __construct(array $data = [])
+ {
+ $this->data = array_replace(self::$defaults, $data);
+ // Extract the Expires value and turn it into a UNIX timestamp if needed
+ if (!$this->getExpires() && $this->getMaxAge()) {
+ // Calculate the Expires date
+ $this->setExpires(time() + $this->getMaxAge());
+ } elseif ($this->getExpires() && !is_numeric($this->getExpires())) {
+ $this->setExpires($this->getExpires());
+ }
+ }
+
+ public function __toString()
+ {
+ $str = $this->data['Name'] . '=' . $this->data['Value'] . '; ';
+ foreach ($this->data as $k => $v) {
+ if ($k != 'Name' && $k != 'Value' && $v !== null && $v !== false) {
+ if ($k == 'Expires') {
+ $str .= 'Expires=' . gmdate('D, d M Y H:i:s \G\M\T', $v) . '; ';
+ } else {
+ $str .= ($v === true ? $k : "{$k}={$v}") . '; ';
+ }
+ }
+ }
+
+ return rtrim($str, '; ');
+ }
+
+ public function toArray()
+ {
+ return $this->data;
+ }
+
+ /**
+ * Get the cookie name
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->data['Name'];
+ }
+
+ /**
+ * Set the cookie name
+ *
+ * @param string $name Cookie name
+ */
+ public function setName($name)
+ {
+ $this->data['Name'] = $name;
+ }
+
+ /**
+ * Get the cookie value
+ *
+ * @return string
+ */
+ public function getValue()
+ {
+ return $this->data['Value'];
+ }
+
+ /**
+ * Set the cookie value
+ *
+ * @param string $value Cookie value
+ */
+ public function setValue($value)
+ {
+ $this->data['Value'] = $value;
+ }
+
+ /**
+ * Get the domain
+ *
+ * @return string|null
+ */
+ public function getDomain()
+ {
+ return $this->data['Domain'];
+ }
+
+ /**
+ * Set the domain of the cookie
+ *
+ * @param string $domain
+ */
+ public function setDomain($domain)
+ {
+ $this->data['Domain'] = $domain;
+ }
+
+ /**
+ * Get the path
+ *
+ * @return string
+ */
+ public function getPath()
+ {
+ return $this->data['Path'];
+ }
+
+ /**
+ * Set the path of the cookie
+ *
+ * @param string $path Path of the cookie
+ */
+ public function setPath($path)
+ {
+ $this->data['Path'] = $path;
+ }
+
+ /**
+ * Maximum lifetime of the cookie in seconds
+ *
+ * @return int|null
+ */
+ public function getMaxAge()
+ {
+ return $this->data['Max-Age'];
+ }
+
+ /**
+ * Set the max-age of the cookie
+ *
+ * @param int $maxAge Max age of the cookie in seconds
+ */
+ public function setMaxAge($maxAge)
+ {
+ $this->data['Max-Age'] = $maxAge;
+ }
+
+ /**
+ * The UNIX timestamp when the cookie Expires
+ *
+ * @return mixed
+ */
+ public function getExpires()
+ {
+ return $this->data['Expires'];
+ }
+
+ /**
+ * Set the unix timestamp for which the cookie will expire
+ *
+ * @param int $timestamp Unix timestamp
+ */
+ public function setExpires($timestamp)
+ {
+ $this->data['Expires'] = is_numeric($timestamp)
+ ? (int) $timestamp
+ : strtotime($timestamp);
+ }
+
+ /**
+ * Get whether or not this is a secure cookie
+ *
+ * @return null|bool
+ */
+ public function getSecure()
+ {
+ return $this->data['Secure'];
+ }
+
+ /**
+ * Set whether or not the cookie is secure
+ *
+ * @param bool $secure Set to true or false if secure
+ */
+ public function setSecure($secure)
+ {
+ $this->data['Secure'] = $secure;
+ }
+
+ /**
+ * Get whether or not this is a session cookie
+ *
+ * @return null|bool
+ */
+ public function getDiscard()
+ {
+ return $this->data['Discard'];
+ }
+
+ /**
+ * Set whether or not this is a session cookie
+ *
+ * @param bool $discard Set to true or false if this is a session cookie
+ */
+ public function setDiscard($discard)
+ {
+ $this->data['Discard'] = $discard;
+ }
+
+ /**
+ * Get whether or not this is an HTTP only cookie
+ *
+ * @return bool
+ */
+ public function getHttpOnly()
+ {
+ return $this->data['HttpOnly'];
+ }
+
+ /**
+ * Set whether or not this is an HTTP only cookie
+ *
+ * @param bool $httpOnly Set to true or false if this is HTTP only
+ */
+ public function setHttpOnly($httpOnly)
+ {
+ $this->data['HttpOnly'] = $httpOnly;
+ }
+
+ /**
+ * Check if the cookie matches a path value.
+ *
+ * A request-path path-matches a given cookie-path if at least one of
+ * the following conditions holds:
+ *
+ * - The cookie-path and the request-path are identical.
+ * - The cookie-path is a prefix of the request-path, and the last
+ * character of the cookie-path is %x2F ("/").
+ * - The cookie-path is a prefix of the request-path, and the first
+ * character of the request-path that is not included in the cookie-
+ * path is a %x2F ("/") character.
+ *
+ * @param string $requestPath Path to check against
+ *
+ * @return bool
+ */
+ public function matchesPath($requestPath)
+ {
+ $cookiePath = $this->getPath();
+
+ // Match on exact matches or when path is the default empty "/"
+ if ($cookiePath == '/' || $cookiePath == $requestPath) {
+ return true;
+ }
+
+ // Ensure that the cookie-path is a prefix of the request path.
+ if (0 !== strpos($requestPath, $cookiePath)) {
+ return false;
+ }
+
+ // Match if the last character of the cookie-path is "/"
+ if (substr($cookiePath, -1, 1) == '/') {
+ return true;
+ }
+
+ // Match if the first character not included in cookie path is "/"
+ return substr($requestPath, strlen($cookiePath), 1) == '/';
+ }
+
+ /**
+ * Check if the cookie matches a domain value
+ *
+ * @param string $domain Domain to check against
+ *
+ * @return bool
+ */
+ public function matchesDomain($domain)
+ {
+ // Remove the leading '.' as per spec in RFC 6265.
+ // http://tools.ietf.org/html/rfc6265#section-5.2.3
+ $cookieDomain = ltrim($this->getDomain(), '.');
+
+ // Domain not set or exact match.
+ if (!$cookieDomain || !strcasecmp($domain, $cookieDomain)) {
+ return true;
+ }
+
+ // Matching the subdomain according to RFC 6265.
+ // http://tools.ietf.org/html/rfc6265#section-5.1.3
+ if (filter_var($domain, FILTER_VALIDATE_IP)) {
+ return false;
+ }
+
+ return (bool) preg_match('/\.' . preg_quote($cookieDomain) . '$/', $domain);
+ }
+
+ /**
+ * Check if the cookie is expired
+ *
+ * @return bool
+ */
+ public function isExpired()
+ {
+ return $this->getExpires() && time() > $this->getExpires();
+ }
+
+ /**
+ * Check if the cookie is valid according to RFC 6265
+ *
+ * @return bool|string Returns true if valid or an error message if invalid
+ */
+ public function validate()
+ {
+ // Names must not be empty, but can be 0
+ $name = $this->getName();
+ if (empty($name) && !is_numeric($name)) {
+ return 'The cookie name must not be empty';
+ }
+
+ // Check if any of the invalid characters are present in the cookie name
+ if (preg_match(
+ '/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5c\x7b\x7d\x7f]/',
+ $name)
+ ) {
+ return 'Cookie name must not contain invalid characters: ASCII '
+ . 'Control characters (0-31;127), space, tab and the '
+ . 'following characters: ()<>@,;:\"/?={}';
+ }
+
+ // Value must not be empty, but can be 0
+ $value = $this->getValue();
+ if (empty($value) && !is_numeric($value)) {
+ return 'The cookie value must not be empty';
+ }
+
+ // Domains must not be empty, but can be 0
+ // A "0" is not a valid internet domain, but may be used as server name
+ // in a private network.
+ $domain = $this->getDomain();
+ if (empty($domain) && !is_numeric($domain)) {
+ return 'The cookie domain must not be empty';
+ }
+
+ return true;
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php b/server/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php
new file mode 100644
index 0000000..fd78431
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php
@@ -0,0 +1,7 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+/**
+ * Exception when an HTTP error occurs (4xx or 5xx error)
+ */
+class BadResponseException extends RequestException {}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php b/server/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php
new file mode 100644
index 0000000..f95c09f
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php
@@ -0,0 +1,7 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+/**
+ * Exception when a client error is encountered (4xx codes)
+ */
+class ClientException extends BadResponseException {}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php b/server/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php
new file mode 100644
index 0000000..d33b0cc
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php
@@ -0,0 +1,37 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Exception thrown when a connection cannot be established.
+ *
+ * Note that no response is present for a ConnectException
+ */
+class ConnectException extends RequestException
+{
+ public function __construct(
+ $message,
+ RequestInterface $request,
+ \Exception $previous = null,
+ array $handlerContext = []
+ ) {
+ parent::__construct($message, $request, null, $previous, $handlerContext);
+ }
+
+ /**
+ * @return null
+ */
+ public function getResponse()
+ {
+ return null;
+ }
+
+ /**
+ * @return bool
+ */
+ public function hasResponse()
+ {
+ return false;
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php b/server/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php
new file mode 100644
index 0000000..c82998e
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php
@@ -0,0 +1,4 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+interface GuzzleException {}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php b/server/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php
new file mode 100644
index 0000000..56b1831
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php
@@ -0,0 +1,188 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use GuzzleHttp\Promise\PromiseInterface;
+
+/**
+ * HTTP Request exception
+ */
+class RequestException extends TransferException
+{
+ /** @var RequestInterface */
+ private $request;
+
+ /** @var ResponseInterface */
+ private $response;
+
+ /** @var array */
+ private $handlerContext;
+
+ public function __construct(
+ $message,
+ RequestInterface $request,
+ ResponseInterface $response = null,
+ \Exception $previous = null,
+ array $handlerContext = []
+ ) {
+ // Set the code of the exception if the response is set and not future.
+ $code = $response && !($response instanceof PromiseInterface)
+ ? $response->getStatusCode()
+ : 0;
+ parent::__construct($message, $code, $previous);
+ $this->request = $request;
+ $this->response = $response;
+ $this->handlerContext = $handlerContext;
+ }
+
+ /**
+ * Wrap non-RequestExceptions with a RequestException
+ *
+ * @param RequestInterface $request
+ * @param \Exception $e
+ *
+ * @return RequestException
+ */
+ public static function wrapException(RequestInterface $request, \Exception $e)
+ {
+ return $e instanceof RequestException
+ ? $e
+ : new RequestException($e->getMessage(), $request, null, $e);
+ }
+
+ /**
+ * Factory method to create a new exception with a normalized error message
+ *
+ * @param RequestInterface $request Request
+ * @param ResponseInterface $response Response received
+ * @param \Exception $previous Previous exception
+ * @param array $ctx Optional handler context.
+ *
+ * @return self
+ */
+ public static function create(
+ RequestInterface $request,
+ ResponseInterface $response = null,
+ \Exception $previous = null,
+ array $ctx = []
+ ) {
+ if (!$response) {
+ return new self(
+ 'Error completing request',
+ $request,
+ null,
+ $previous,
+ $ctx
+ );
+ }
+
+ $level = floor($response->getStatusCode() / 100);
+ if ($level == '4') {
+ $label = 'Client error';
+ $className = __NAMESPACE__ . '\\ClientException';
+ } elseif ($level == '5') {
+ $label = 'Server error';
+ $className = __NAMESPACE__ . '\\ServerException';
+ } else {
+ $label = 'Unsuccessful request';
+ $className = __CLASS__;
+ }
+
+ // Server Error: `GET /` resulted in a `404 Not Found` response:
+ // <html> ... (truncated)
+ $message = sprintf(
+ '%s: `%s` resulted in a `%s` response',
+ $label,
+ $request->getMethod() . ' ' . $request->getUri(),
+ $response->getStatusCode() . ' ' . $response->getReasonPhrase()
+ );
+
+ $summary = static::getResponseBodySummary($response);
+
+ if ($summary !== null) {
+ $message .= ":\n{$summary}\n";
+ }
+
+ return new $className($message, $request, $response, $previous, $ctx);
+ }
+
+ /**
+ * Get a short summary of the response
+ *
+ * Will return `null` if the response is not printable.
+ *
+ * @param ResponseInterface $response
+ *
+ * @return string|null
+ */
+ public static function getResponseBodySummary(ResponseInterface $response)
+ {
+ $body = $response->getBody();
+
+ if (!$body->isSeekable()) {
+ return null;
+ }
+
+ $size = $body->getSize();
+ $summary = $body->read(120);
+ $body->rewind();
+
+ if ($size > 120) {
+ $summary .= ' (truncated...)';
+ }
+
+ // Matches any printable character, including unicode characters:
+ // letters, marks, numbers, punctuation, spacing, and separators.
+ if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/', $summary)) {
+ return null;
+ }
+
+ return $summary;
+ }
+
+ /**
+ * Get the request that caused the exception
+ *
+ * @return RequestInterface
+ */
+ public function getRequest()
+ {
+ return $this->request;
+ }
+
+ /**
+ * Get the associated response
+ *
+ * @return ResponseInterface|null
+ */
+ public function getResponse()
+ {
+ return $this->response;
+ }
+
+ /**
+ * Check if a response was received
+ *
+ * @return bool
+ */
+ public function hasResponse()
+ {
+ return $this->response !== null;
+ }
+
+ /**
+ * Get contextual information about the error from the underlying handler.
+ *
+ * The contents of this array will vary depending on which handler you are
+ * using. It may also be just an empty array. Relying on this data will
+ * couple you to a specific handler, but can give more debug information
+ * when needed.
+ *
+ * @return array
+ */
+ public function getHandlerContext()
+ {
+ return $this->handlerContext;
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Exception/SeekException.php b/server/vendor/guzzlehttp/guzzle/src/Exception/SeekException.php
new file mode 100644
index 0000000..a77c289
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Exception/SeekException.php
@@ -0,0 +1,27 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Exception thrown when a seek fails on a stream.
+ */
+class SeekException extends \RuntimeException implements GuzzleException
+{
+ private $stream;
+
+ public function __construct(StreamInterface $stream, $pos = 0, $msg = '')
+ {
+ $this->stream = $stream;
+ $msg = $msg ?: 'Could not seek the stream to position ' . $pos;
+ parent::__construct($msg);
+ }
+
+ /**
+ * @return StreamInterface
+ */
+ public function getStream()
+ {
+ return $this->stream;
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php b/server/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php
new file mode 100644
index 0000000..7cdd340
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php
@@ -0,0 +1,7 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+/**
+ * Exception when a server error is encountered (5xx codes)
+ */
+class ServerException extends BadResponseException {}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php b/server/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php
new file mode 100644
index 0000000..b60a967
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php
@@ -0,0 +1,4 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+class TooManyRedirectsException extends RequestException {}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php b/server/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php
new file mode 100644
index 0000000..b92071c
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php
@@ -0,0 +1,4 @@
+<?php
+namespace GuzzleHttp\Exception;
+
+class TransferException extends \RuntimeException implements GuzzleException {}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php b/server/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php
new file mode 100644
index 0000000..e8d9388
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php
@@ -0,0 +1,531 @@
+<?php
+namespace GuzzleHttp\Handler;
+
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Exception\ConnectException;
+use GuzzleHttp\Promise\FulfilledPromise;
+use GuzzleHttp\Promise\RejectedPromise;
+use GuzzleHttp\Psr7;
+use GuzzleHttp\Psr7\LazyOpenStream;
+use GuzzleHttp\TransferStats;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Creates curl resources from a request
+ */
+class CurlFactory implements CurlFactoryInterface
+{
+ /** @var array */
+ private $handles;
+
+ /** @var int Total number of idle handles to keep in cache */
+ private $maxHandles;
+
+ /**
+ * @param int $maxHandles Maximum number of idle handles.
+ */
+ public function __construct($maxHandles)
+ {
+ $this->maxHandles = $maxHandles;
+ }
+
+ public function create(RequestInterface $request, array $options)
+ {
+ if (isset($options['curl']['body_as_string'])) {
+ $options['_body_as_string'] = $options['curl']['body_as_string'];
+ unset($options['curl']['body_as_string']);
+ }
+
+ $easy = new EasyHandle;
+ $easy->request = $request;
+ $easy->options = $options;
+ $conf = $this->getDefaultConf($easy);
+ $this->applyMethod($easy, $conf);
+ $this->applyHandlerOptions($easy, $conf);
+ $this->applyHeaders($easy, $conf);
+ unset($conf['_headers']);
+
+ // Add handler options from the request configuration options
+ if (isset($options['curl'])) {
+ $conf = array_replace($conf, $options['curl']);
+ }
+
+ $conf[CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy);
+ $easy->handle = $this->handles
+ ? array_pop($this->handles)
+ : curl_init();
+ curl_setopt_array($easy->handle, $conf);
+
+ return $easy;
+ }
+
+ public function release(EasyHandle $easy)
+ {
+ $resource = $easy->handle;
+ unset($easy->handle);
+
+ if (count($this->handles) >= $this->maxHandles) {
+ curl_close($resource);
+ } else {
+ // Remove all callback functions as they can hold onto references
+ // and are not cleaned up by curl_reset. Using curl_setopt_array
+ // does not work for some reason, so removing each one
+ // individually.
+ curl_setopt($resource, CURLOPT_HEADERFUNCTION, null);
+ curl_setopt($resource, CURLOPT_READFUNCTION, null);
+ curl_setopt($resource, CURLOPT_WRITEFUNCTION, null);
+ curl_setopt($resource, CURLOPT_PROGRESSFUNCTION, null);
+ curl_reset($resource);
+ $this->handles[] = $resource;
+ }
+ }
+
+ /**
+ * Completes a cURL transaction, either returning a response promise or a
+ * rejected promise.
+ *
+ * @param callable $handler
+ * @param EasyHandle $easy
+ * @param CurlFactoryInterface $factory Dictates how the handle is released
+ *
+ * @return \GuzzleHttp\Promise\PromiseInterface
+ */
+ public static function finish(
+ callable $handler,
+ EasyHandle $easy,
+ CurlFactoryInterface $factory
+ ) {
+ if (isset($easy->options['on_stats'])) {
+ self::invokeStats($easy);
+ }
+
+ if (!$easy->response || $easy->errno) {
+ return self::finishError($handler, $easy, $factory);
+ }
+
+ // Return the response if it is present and there is no error.
+ $factory->release($easy);
+
+ // Rewind the body of the response if possible.
+ $body = $easy->response->getBody();
+ if ($body->isSeekable()) {
+ $body->rewind();
+ }
+
+ return new FulfilledPromise($easy->response);
+ }
+
+ private static function invokeStats(EasyHandle $easy)
+ {
+ $curlStats = curl_getinfo($easy->handle);
+ $stats = new TransferStats(
+ $easy->request,
+ $easy->response,
+ $curlStats['total_time'],
+ $easy->errno,
+ $curlStats
+ );
+ call_user_func($easy->options['on_stats'], $stats);
+ }
+
+ private static function finishError(
+ callable $handler,
+ EasyHandle $easy,
+ CurlFactoryInterface $factory
+ ) {
+ // Get error information and release the handle to the factory.
+ $ctx = [
+ 'errno' => $easy->errno,
+ 'error' => curl_error($easy->handle),
+ ] + curl_getinfo($easy->handle);
+ $factory->release($easy);
+
+ // Retry when nothing is present or when curl failed to rewind.
+ if (empty($easy->options['_err_message'])
+ && (!$easy->errno || $easy->errno == 65)
+ ) {
+ return self::retryFailedRewind($handler, $easy, $ctx);
+ }
+
+ return self::createRejection($easy, $ctx);
+ }
+
+ private static function createRejection(EasyHandle $easy, array $ctx)
+ {
+ static $connectionErrors = [
+ CURLE_OPERATION_TIMEOUTED => true,
+ CURLE_COULDNT_RESOLVE_HOST => true,
+ CURLE_COULDNT_CONNECT => true,
+ CURLE_SSL_CONNECT_ERROR => true,
+ CURLE_GOT_NOTHING => true,
+ ];
+
+ // If an exception was encountered during the onHeaders event, then
+ // return a rejected promise that wraps that exception.
+ if ($easy->onHeadersException) {
+ return new RejectedPromise(
+ new RequestException(
+ 'An error was encountered during the on_headers event',
+ $easy->request,
+ $easy->response,
+ $easy->onHeadersException,
+ $ctx
+ )
+ );
+ }
+
+ $message = sprintf(
+ 'cURL error %s: %s (%s)',
+ $ctx['errno'],
+ $ctx['error'],
+ 'see http://curl.haxx.se/libcurl/c/libcurl-errors.html'
+ );
+
+ // Create a connection exception if it was a specific error code.
+ $error = isset($connectionErrors[$easy->errno])
+ ? new ConnectException($message, $easy->request, null, $ctx)
+ : new RequestException($message, $easy->request, $easy->response, null, $ctx);
+
+ return new RejectedPromise($error);
+ }
+
+ private function getDefaultConf(EasyHandle $easy)
+ {
+ $conf = [
+ '_headers' => $easy->request->getHeaders(),
+ CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(),
+ CURLOPT_URL => (string) $easy->request->getUri(),
+ CURLOPT_RETURNTRANSFER => false,
+ CURLOPT_HEADER => false,
+ CURLOPT_CONNECTTIMEOUT => 150,
+ ];
+
+ if (defined('CURLOPT_PROTOCOLS')) {
+ $conf[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
+ }
+
+ $version = $easy->request->getProtocolVersion();
+ if ($version == 1.1) {
+ $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
+ } elseif ($version == 2.0) {
+ $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0;
+ } else {
+ $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0;
+ }
+
+ return $conf;
+ }
+
+ private function applyMethod(EasyHandle $easy, array &$conf)
+ {
+ $body = $easy->request->getBody();
+ $size = $body->getSize();
+
+ if ($size === null || $size > 0) {
+ $this->applyBody($easy->request, $easy->options, $conf);
+ return;
+ }
+
+ $method = $easy->request->getMethod();
+ if ($method === 'PUT' || $method === 'POST') {
+ // See http://tools.ietf.org/html/rfc7230#section-3.3.2
+ if (!$easy->request->hasHeader('Content-Length')) {
+ $conf[CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
+ }
+ } elseif ($method === 'HEAD') {
+ $conf[CURLOPT_NOBODY] = true;
+ unset(
+ $conf[CURLOPT_WRITEFUNCTION],
+ $conf[CURLOPT_READFUNCTION],
+ $conf[CURLOPT_FILE],
+ $conf[CURLOPT_INFILE]
+ );
+ }
+ }
+
+ private function applyBody(RequestInterface $request, array $options, array &$conf)
+ {
+ $size = $request->hasHeader('Content-Length')
+ ? (int) $request->getHeaderLine('Content-Length')
+ : null;
+
+ // Send the body as a string if the size is less than 1MB OR if the
+ // [curl][body_as_string] request value is set.
+ if (($size !== null && $size < 1000000) ||
+ !empty($options['_body_as_string'])
+ ) {
+ $conf[CURLOPT_POSTFIELDS] = (string) $request->getBody();
+ // Don't duplicate the Content-Length header
+ $this->removeHeader('Content-Length', $conf);
+ $this->removeHeader('Transfer-Encoding', $conf);
+ } else {
+ $conf[CURLOPT_UPLOAD] = true;
+ if ($size !== null) {
+ $conf[CURLOPT_INFILESIZE] = $size;
+ $this->removeHeader('Content-Length', $conf);
+ }
+ $body = $request->getBody();
+ $conf[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) {
+ return $body->read($length);
+ };
+ }
+
+ // If the Expect header is not present, prevent curl from adding it
+ if (!$request->hasHeader('Expect')) {
+ $conf[CURLOPT_HTTPHEADER][] = 'Expect:';
+ }
+
+ // cURL sometimes adds a content-type by default. Prevent this.
+ if (!$request->hasHeader('Content-Type')) {
+ $conf[CURLOPT_HTTPHEADER][] = 'Content-Type:';
+ }
+ }
+
+ private function applyHeaders(EasyHandle $easy, array &$conf)
+ {
+ foreach ($conf['_headers'] as $name => $values) {
+ foreach ($values as $value) {
+ $conf[CURLOPT_HTTPHEADER][] = "$name: $value";
+ }
+ }
+
+ // Remove the Accept header if one was not set
+ if (!$easy->request->hasHeader('Accept')) {
+ $conf[CURLOPT_HTTPHEADER][] = 'Accept:';
+ }
+ }
+
+ /**
+ * Remove a header from the options array.
+ *
+ * @param string $name Case-insensitive header to remove
+ * @param array $options Array of options to modify
+ */
+ private function removeHeader($name, array &$options)
+ {
+ foreach (array_keys($options['_headers']) as $key) {
+ if (!strcasecmp($key, $name)) {
+ unset($options['_headers'][$key]);
+ return;
+ }
+ }
+ }
+
+ private function applyHandlerOptions(EasyHandle $easy, array &$conf)
+ {
+ $options = $easy->options;
+ if (isset($options['verify'])) {
+ if ($options['verify'] === false) {
+ unset($conf[CURLOPT_CAINFO]);
+ $conf[CURLOPT_SSL_VERIFYHOST] = 0;
+ $conf[CURLOPT_SSL_VERIFYPEER] = false;
+ } else {
+ $conf[CURLOPT_SSL_VERIFYHOST] = 2;
+ $conf[CURLOPT_SSL_VERIFYPEER] = true;
+ if (is_string($options['verify'])) {
+ $conf[CURLOPT_CAINFO] = $options['verify'];
+ if (!file_exists($options['verify'])) {
+ throw new \InvalidArgumentException(
+ "SSL CA bundle not found: {$options['verify']}"
+ );
+ }
+ }
+ }
+ }
+
+ if (!empty($options['decode_content'])) {
+ $accept = $easy->request->getHeaderLine('Accept-Encoding');
+ if ($accept) {
+ $conf[CURLOPT_ENCODING] = $accept;
+ } else {
+ $conf[CURLOPT_ENCODING] = '';
+ // Don't let curl send the header over the wire
+ $conf[CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
+ }
+ }
+
+ if (isset($options['sink'])) {
+ $sink = $options['sink'];
+ if (!is_string($sink)) {
+ $sink = \GuzzleHttp\Psr7\stream_for($sink);
+ } elseif (!is_dir(dirname($sink))) {
+ // Ensure that the directory exists before failing in curl.
+ throw new \RuntimeException(sprintf(
+ 'Directory %s does not exist for sink value of %s',
+ dirname($sink),
+ $sink
+ ));
+ } else {
+ $sink = new LazyOpenStream($sink, 'w+');
+ }
+ $easy->sink = $sink;
+ $conf[CURLOPT_WRITEFUNCTION] = function ($ch, $write) use ($sink) {
+ return $sink->write($write);
+ };
+ } else {
+ // Use a default temp stream if no sink was set.
+ $conf[CURLOPT_FILE] = fopen('php://temp', 'w+');
+ $easy->sink = Psr7\stream_for($conf[CURLOPT_FILE]);
+ }
+
+ if (isset($options['timeout'])) {
+ $conf[CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000;
+ }
+
+ if (isset($options['connect_timeout'])) {
+ $conf[CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000;
+ }
+
+ if (isset($options['proxy'])) {
+ if (!is_array($options['proxy'])) {
+ $conf[CURLOPT_PROXY] = $options['proxy'];
+ } else {
+ $scheme = $easy->request->getUri()->getScheme();
+ if (isset($options['proxy'][$scheme])) {
+ $host = $easy->request->getUri()->getHost();
+ if (!isset($options['proxy']['no']) ||
+ !\GuzzleHttp\is_host_in_noproxy($host, $options['proxy']['no'])
+ ) {
+ $conf[CURLOPT_PROXY] = $options['proxy'][$scheme];
+ }
+ }
+ }
+ }
+
+ if (isset($options['cert'])) {
+ $cert = $options['cert'];
+ if (is_array($cert)) {
+ $conf[CURLOPT_SSLCERTPASSWD] = $cert[1];
+ $cert = $cert[0];
+ }
+ if (!file_exists($cert)) {
+ throw new \InvalidArgumentException(
+ "SSL certificate not found: {$cert}"
+ );
+ }
+ $conf[CURLOPT_SSLCERT] = $cert;
+ }
+
+ if (isset($options['ssl_key'])) {
+ $sslKey = $options['ssl_key'];
+ if (is_array($sslKey)) {
+ $conf[CURLOPT_SSLKEYPASSWD] = $sslKey[1];
+ $sslKey = $sslKey[0];
+ }
+ if (!file_exists($sslKey)) {
+ throw new \InvalidArgumentException(
+ "SSL private key not found: {$sslKey}"
+ );
+ }
+ $conf[CURLOPT_SSLKEY] = $sslKey;
+ }
+
+ if (isset($options['progress'])) {
+ $progress = $options['progress'];
+ if (!is_callable($progress)) {
+ throw new \InvalidArgumentException(
+ 'progress client option must be callable'
+ );
+ }
+ $conf[CURLOPT_NOPROGRESS] = false;
+ $conf[CURLOPT_PROGRESSFUNCTION] = function () use ($progress) {
+ $args = func_get_args();
+ // PHP 5.5 pushed the handle onto the start of the args
+ if (is_resource($args[0])) {
+ array_shift($args);
+ }
+ call_user_func_array($progress, $args);
+ };
+ }
+
+ if (!empty($options['debug'])) {
+ $conf[CURLOPT_STDERR] = \GuzzleHttp\debug_resource($options['debug']);
+ $conf[CURLOPT_VERBOSE] = true;
+ }
+ }
+
+ /**
+ * This function ensures that a response was set on a transaction. If one
+ * was not set, then the request is retried if possible. This error
+ * typically means you are sending a payload, curl encountered a
+ * "Connection died, retrying a fresh connect" error, tried to rewind the
+ * stream, and then encountered a "necessary data rewind wasn't possible"
+ * error, causing the request to be sent through curl_multi_info_read()
+ * without an error status.
+ */
+ private static function retryFailedRewind(
+ callable $handler,
+ EasyHandle $easy,
+ array $ctx
+ ) {
+ try {
+ // Only rewind if the body has been read from.
+ $body = $easy->request->getBody();
+ if ($body->tell() > 0) {
+ $body->rewind();
+ }
+ } catch (\RuntimeException $e) {
+ $ctx['error'] = 'The connection unexpectedly failed without '
+ . 'providing an error. The request would have been retried, '
+ . 'but attempting to rewind the request body failed. '
+ . 'Exception: ' . $e;
+ return self::createRejection($easy, $ctx);
+ }
+
+ // Retry no more than 3 times before giving up.
+ if (!isset($easy->options['_curl_retries'])) {
+ $easy->options['_curl_retries'] = 1;
+ } elseif ($easy->options['_curl_retries'] == 2) {
+ $ctx['error'] = 'The cURL request was retried 3 times '
+ . 'and did not succeed. The most likely reason for the failure '
+ . 'is that cURL was unable to rewind the body of the request '
+ . 'and subsequent retries resulted in the same error. Turn on '
+ . 'the debug option to see what went wrong. See '
+ . 'https://bugs.php.net/bug.php?id=47204 for more information.';
+ return self::createRejection($easy, $ctx);
+ } else {
+ $easy->options['_curl_retries']++;
+ }
+
+ return $handler($easy->request, $easy->options);
+ }
+
+ private function createHeaderFn(EasyHandle $easy)
+ {
+ if (!isset($easy->options['on_headers'])) {
+ $onHeaders = null;
+ } elseif (!is_callable($easy->options['on_headers'])) {
+ throw new \InvalidArgumentException('on_headers must be callable');
+ } else {
+ $onHeaders = $easy->options['on_headers'];
+ }
+
+ return function ($ch, $h) use (
+ $onHeaders,
+ $easy,
+ &$startingResponse
+ ) {
+ $value = trim($h);
+ if ($value === '') {
+ $startingResponse = true;
+ $easy->createResponse();
+ if ($onHeaders) {
+ try {
+ $onHeaders($easy->response);
+ } catch (\Exception $e) {
+ // Associate the exception with the handle and trigger
+ // a curl header write error by returning 0.
+ $easy->onHeadersException = $e;
+ return -1;
+ }
+ }
+ } elseif ($startingResponse) {
+ $startingResponse = false;
+ $easy->headers = [$value];
+ } else {
+ $easy->headers[] = $value;
+ }
+ return strlen($h);
+ };
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php b/server/vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php
new file mode 100644
index 0000000..b0fc236
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php
@@ -0,0 +1,27 @@
+<?php
+namespace GuzzleHttp\Handler;
+
+use Psr\Http\Message\RequestInterface;
+
+interface CurlFactoryInterface
+{
+ /**
+ * Creates a cURL handle resource.
+ *
+ * @param RequestInterface $request Request
+ * @param array $options Transfer options
+ *
+ * @return EasyHandle
+ * @throws \RuntimeException when an option cannot be applied
+ */
+ public function create(RequestInterface $request, array $options);
+
+ /**
+ * Release an easy handle, allowing it to be reused or closed.
+ *
+ * This function must call unset on the easy handle's "handle" property.
+ *
+ * @param EasyHandle $easy
+ */
+ public function release(EasyHandle $easy);
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php b/server/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php
new file mode 100644
index 0000000..43577da
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php
@@ -0,0 +1,45 @@
+<?php
+namespace GuzzleHttp\Handler;
+
+use GuzzleHttp\Psr7;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * HTTP handler that uses cURL easy handles as a transport layer.
+ *
+ * When using the CurlHandler, custom curl options can be specified as an
+ * associative array of curl option constants mapping to values in the
+ * **curl** key of the "client" key of the request.
+ */
+class CurlHandler
+{
+ /** @var CurlFactoryInterface */
+ private $factory;
+
+ /**
+ * Accepts an associative array of options:
+ *
+ * - factory: Optional curl factory used to create cURL handles.
+ *
+ * @param array $options Array of options to use with the handler
+ */
+ public function __construct(array $options = [])
+ {
+ $this->factory = isset($options['handle_factory'])
+ ? $options['handle_factory']
+ : new CurlFactory(3);
+ }
+
+ public function __invoke(RequestInterface $request, array $options)
+ {
+ if (isset($options['delay'])) {
+ usleep($options['delay'] * 1000);
+ }
+
+ $easy = $this->factory->create($request, $options);
+ curl_exec($easy->handle);
+ $easy->errno = curl_errno($easy->handle);
+
+ return CurlFactory::finish($this, $easy, $this->factory);
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php b/server/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php
new file mode 100644
index 0000000..417850b
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php
@@ -0,0 +1,197 @@
+<?php
+namespace GuzzleHttp\Handler;
+
+use GuzzleHttp\Promise as P;
+use GuzzleHttp\Promise\Promise;
+use GuzzleHttp\Psr7;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Returns an asynchronous response using curl_multi_* functions.
+ *
+ * When using the CurlMultiHandler, custom curl options can be specified as an
+ * associative array of curl option constants mapping to values in the
+ * **curl** key of the provided request options.
+ *
+ * @property resource $_mh Internal use only. Lazy loaded multi-handle.
+ */
+class CurlMultiHandler
+{
+ /** @var CurlFactoryInterface */
+ private $factory;
+ private $selectTimeout;
+ private $active;
+ private $handles = [];
+ private $delays = [];
+
+ /**
+ * This handler accepts the following options:
+ *
+ * - handle_factory: An optional factory used to create curl handles
+ * - select_timeout: Optional timeout (in seconds) to block before timing
+ * out while selecting curl handles. Defaults to 1 second.
+ *
+ * @param array $options
+ */
+ public function __construct(array $options = [])
+ {
+ $this->factory = isset($options['handle_factory'])
+ ? $options['handle_factory'] : new CurlFactory(50);
+ $this->selectTimeout = isset($options['select_timeout'])
+ ? $options['select_timeout'] : 1;
+ }
+
+ public function __get($name)
+ {
+ if ($name === '_mh') {
+ return $this->_mh = curl_multi_init();
+ }
+
+ throw new \BadMethodCallException();
+ }
+
+ public function __destruct()
+ {
+ if (isset($this->_mh)) {
+ curl_multi_close($this->_mh);
+ unset($this->_mh);
+ }
+ }
+
+ public function __invoke(RequestInterface $request, array $options)
+ {
+ $easy = $this->factory->create($request, $options);
+ $id = (int) $easy->handle;
+
+ $promise = new Promise(
+ [$this, 'execute'],
+ function () use ($id) { return $this->cancel($id); }
+ );
+
+ $this->addRequest(['easy' => $easy, 'deferred' => $promise]);
+
+ return $promise;
+ }
+
+ /**
+ * Ticks the curl event loop.
+ */
+ public function tick()
+ {
+ // Add any delayed handles if needed.
+ if ($this->delays) {
+ $currentTime = microtime(true);
+ foreach ($this->delays as $id => $delay) {
+ if ($currentTime >= $delay) {
+ unset($this->delays[$id]);
+ curl_multi_add_handle(
+ $this->_mh,
+ $this->handles[$id]['easy']->handle
+ );
+ }
+ }
+ }
+
+ // Step through the task queue which may add additional requests.
+ P\queue()->run();
+
+ if ($this->active &&
+ curl_multi_select($this->_mh, $this->selectTimeout) === -1
+ ) {
+ // Perform a usleep if a select returns -1.
+ // See: https://bugs.php.net/bug.php?id=61141
+ usleep(250);
+ }
+
+ while (curl_multi_exec($this->_mh, $this->active) === CURLM_CALL_MULTI_PERFORM);
+
+ $this->processMessages();
+ }
+
+ /**
+ * Runs until all outstanding connections have completed.
+ */
+ public function execute()
+ {
+ $queue = P\queue();
+
+ while ($this->handles || !$queue->isEmpty()) {
+ // If there are no transfers, then sleep for the next delay
+ if (!$this->active && $this->delays) {
+ usleep($this->timeToNext());
+ }
+ $this->tick();
+ }
+ }
+
+ private function addRequest(array $entry)
+ {
+ $easy = $entry['easy'];
+ $id = (int) $easy->handle;
+ $this->handles[$id] = $entry;
+ if (empty($easy->options['delay'])) {
+ curl_multi_add_handle($this->_mh, $easy->handle);
+ } else {
+ $this->delays[$id] = microtime(true) + ($easy->options['delay'] / 1000);
+ }
+ }
+
+ /**
+ * Cancels a handle from sending and removes references to it.
+ *
+ * @param int $id Handle ID to cancel and remove.
+ *
+ * @return bool True on success, false on failure.
+ */
+ private function cancel($id)
+ {
+ // Cannot cancel if it has been processed.
+ if (!isset($this->handles[$id])) {
+ return false;
+ }
+
+ $handle = $this->handles[$id]['easy']->handle;
+ unset($this->delays[$id], $this->handles[$id]);
+ curl_multi_remove_handle($this->_mh, $handle);
+ curl_close($handle);
+
+ return true;
+ }
+
+ private function processMessages()
+ {
+ while ($done = curl_multi_info_read($this->_mh)) {
+ $id = (int) $done['handle'];
+ curl_multi_remove_handle($this->_mh, $done['handle']);
+
+ if (!isset($this->handles[$id])) {
+ // Probably was cancelled.
+ continue;
+ }
+
+ $entry = $this->handles[$id];
+ unset($this->handles[$id], $this->delays[$id]);
+ $entry['easy']->errno = $done['result'];
+ $entry['deferred']->resolve(
+ CurlFactory::finish(
+ $this,
+ $entry['easy'],
+ $this->factory
+ )
+ );
+ }
+ }
+
+ private function timeToNext()
+ {
+ $currentTime = microtime(true);
+ $nextTime = PHP_INT_MAX;
+ foreach ($this->delays as $time) {
+ if ($time < $nextTime) {
+ $nextTime = $time;
+ }
+ }
+
+ return max(0, $currentTime - $nextTime);
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php b/server/vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php
new file mode 100644
index 0000000..c4b927e
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php
@@ -0,0 +1,87 @@
+<?php
+namespace GuzzleHttp\Handler;
+
+use GuzzleHttp\Psr7\Response;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Represents a cURL easy handle and the data it populates.
+ *
+ * @internal
+ */
+final class EasyHandle
+{
+ /** @var resource cURL resource */
+ public $handle;
+
+ /** @var StreamInterface Where data is being written */
+ public $sink;
+
+ /** @var array Received HTTP headers so far */
+ public $headers = [];
+
+ /** @var ResponseInterface Received response (if any) */
+ public $response;
+
+ /** @var RequestInterface Request being sent */
+ public $request;
+
+ /** @var array Request options */
+ public $options = [];
+
+ /** @var int cURL error number (if any) */
+ public $errno = 0;
+
+ /** @var \Exception Exception during on_headers (if any) */
+ public $onHeadersException;
+
+ /**
+ * Attach a response to the easy handle based on the received headers.
+ *
+ * @throws \RuntimeException if no headers have been received.
+ */
+ public function createResponse()
+ {
+ if (empty($this->headers)) {
+ throw new \RuntimeException('No headers have been received');
+ }
+
+ // HTTP-version SP status-code SP reason-phrase
+ $startLine = explode(' ', array_shift($this->headers), 3);
+ $headers = \GuzzleHttp\headers_from_lines($this->headers);
+ $normalizedKeys = \GuzzleHttp\normalize_header_keys($headers);
+
+ if (!empty($this->options['decode_content'])
+ && isset($normalizedKeys['content-encoding'])
+ ) {
+ unset($headers[$normalizedKeys['content-encoding']]);
+ if (isset($normalizedKeys['content-length'])) {
+ $bodyLength = (int) $this->sink->getSize();
+ if ($bodyLength) {
+ $headers[$normalizedKeys['content-length']] = $bodyLength;
+ } else {
+ unset($headers[$normalizedKeys['content-length']]);
+ }
+ }
+ }
+
+ // Attach a response to the easy handle with the parsed headers.
+ $this->response = new Response(
+ $startLine[1],
+ $headers,
+ $this->sink,
+ substr($startLine[0], 5),
+ isset($startLine[2]) ? (string) $startLine[2] : null
+ );
+ }
+
+ public function __get($name)
+ {
+ $msg = $name === 'handle'
+ ? 'The EasyHandle has been released'
+ : 'Invalid property: ' . $name;
+ throw new \BadMethodCallException($msg);
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php b/server/vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php
new file mode 100644
index 0000000..cd7898f
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php
@@ -0,0 +1,176 @@
+<?php
+namespace GuzzleHttp\Handler;
+
+use GuzzleHttp\HandlerStack;
+use GuzzleHttp\Promise\PromiseInterface;
+use GuzzleHttp\Promise\RejectedPromise;
+use GuzzleHttp\TransferStats;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Handler that returns responses or throw exceptions from a queue.
+ */
+class MockHandler implements \Countable
+{
+ private $queue;
+ private $lastRequest;
+ private $lastOptions;
+ private $onFulfilled;
+ private $onRejected;
+
+ /**
+ * Creates a new MockHandler that uses the default handler stack list of
+ * middlewares.
+ *
+ * @param array $queue Array of responses, callables, or exceptions.
+ * @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
+ * @param callable $onRejected Callback to invoke when the return value is rejected.
+ *
+ * @return MockHandler
+ */
+ public static function createWithMiddleware(
+ array $queue = null,
+ callable $onFulfilled = null,
+ callable $onRejected = null
+ ) {
+ return HandlerStack::create(new self($queue, $onFulfilled, $onRejected));
+ }
+
+ /**
+ * The passed in value must be an array of
+ * {@see Psr7\Http\Message\ResponseInterface} objects, Exceptions,
+ * callables, or Promises.
+ *
+ * @param array $queue
+ * @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
+ * @param callable $onRejected Callback to invoke when the return value is rejected.
+ */
+ public function __construct(
+ array $queue = null,
+ callable $onFulfilled = null,
+ callable $onRejected = null
+ ) {
+ $this->onFulfilled = $onFulfilled;
+ $this->onRejected = $onRejected;
+
+ if ($queue) {
+ call_user_func_array([$this, 'append'], $queue);
+ }
+ }
+
+ public function __invoke(RequestInterface $request, array $options)
+ {
+ if (!$this->queue) {
+ throw new \OutOfBoundsException('Mock queue is empty');
+ }
+
+ if (isset($options['delay'])) {
+ usleep($options['delay'] * 1000);
+ }
+
+ $this->lastRequest = $request;
+ $this->lastOptions = $options;
+ $response = array_shift($this->queue);
+
+ if (is_callable($response)) {
+ $response = $response($request, $options);
+ }
+
+ $response = $response instanceof \Exception
+ ? new RejectedPromise($response)
+ : \GuzzleHttp\Promise\promise_for($response);
+
+ return $response->then(
+ function ($value) use ($request, $options) {
+ $this->invokeStats($request, $options, $value);
+ if ($this->onFulfilled) {
+ call_user_func($this->onFulfilled, $value);
+ }
+ if (isset($options['sink'])) {
+ $contents = (string) $value->getBody();
+ $sink = $options['sink'];
+
+ if (is_resource($sink)) {
+ fwrite($sink, $contents);
+ } elseif (is_string($sink)) {
+ file_put_contents($sink, $contents);
+ } elseif ($sink instanceof \Psr\Http\Message\StreamInterface) {
+ $sink->write($contents);
+ }
+ }
+
+ return $value;
+ },
+ function ($reason) use ($request, $options) {
+ $this->invokeStats($request, $options, null, $reason);
+ if ($this->onRejected) {
+ call_user_func($this->onRejected, $reason);
+ }
+ return new RejectedPromise($reason);
+ }
+ );
+ }
+
+ /**
+ * Adds one or more variadic requests, exceptions, callables, or promises
+ * to the queue.
+ */
+ public function append()
+ {
+ foreach (func_get_args() as $value) {
+ if ($value instanceof ResponseInterface
+ || $value instanceof \Exception
+ || $value instanceof PromiseInterface
+ || is_callable($value)
+ ) {
+ $this->queue[] = $value;
+ } else {
+ throw new \InvalidArgumentException('Expected a response or '
+ . 'exception. Found ' . \GuzzleHttp\describe_type($value));
+ }
+ }
+ }
+
+ /**
+ * Get the last received request.
+ *
+ * @return RequestInterface
+ */
+ public function getLastRequest()
+ {
+ return $this->lastRequest;
+ }
+
+ /**
+ * Get the last received request options.
+ *
+ * @return RequestInterface
+ */
+ public function getLastOptions()
+ {
+ return $this->lastOptions;
+ }
+
+ /**
+ * Returns the number of remaining items in the queue.
+ *
+ * @return int
+ */
+ public function count()
+ {
+ return count($this->queue);
+ }
+
+ private function invokeStats(
+ RequestInterface $request,
+ array $options,
+ ResponseInterface $response = null,
+ $reason = null
+ ) {
+ if (isset($options['on_stats'])) {
+ $stats = new TransferStats($request, $response, 0, $reason);
+ call_user_func($options['on_stats'], $stats);
+ }
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php b/server/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php
new file mode 100644
index 0000000..f8b00be
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php
@@ -0,0 +1,55 @@
+<?php
+namespace GuzzleHttp\Handler;
+
+use GuzzleHttp\RequestOptions;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Provides basic proxies for handlers.
+ */
+class Proxy
+{
+ /**
+ * Sends synchronous requests to a specific handler while sending all other
+ * requests to another handler.
+ *
+ * @param callable $default Handler used for normal responses
+ * @param callable $sync Handler used for synchronous responses.
+ *
+ * @return callable Returns the composed handler.
+ */
+ public static function wrapSync(
+ callable $default,
+ callable $sync
+ ) {
+ return function (RequestInterface $request, array $options) use ($default, $sync) {
+ return empty($options[RequestOptions::SYNCHRONOUS])
+ ? $default($request, $options)
+ : $sync($request, $options);
+ };
+ }
+
+ /**
+ * Sends streaming requests to a streaming compatible handler while sending
+ * all other requests to a default handler.
+ *
+ * This, for example, could be useful for taking advantage of the
+ * performance benefits of curl while still supporting true streaming
+ * through the StreamHandler.
+ *
+ * @param callable $default Handler used for non-streaming responses
+ * @param callable $streaming Handler used for streaming responses
+ *
+ * @return callable Returns the composed handler.
+ */
+ public static function wrapStreaming(
+ callable $default,
+ callable $streaming
+ ) {
+ return function (RequestInterface $request, array $options) use ($default, $streaming) {
+ return empty($options['stream'])
+ ? $default($request, $options)
+ : $streaming($request, $options);
+ };
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php b/server/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php
new file mode 100644
index 0000000..c835dc7
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php
@@ -0,0 +1,458 @@
+<?php
+namespace GuzzleHttp\Handler;
+
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Exception\ConnectException;
+use GuzzleHttp\Promise\FulfilledPromise;
+use GuzzleHttp\Promise\RejectedPromise;
+use GuzzleHttp\Promise\PromiseInterface;
+use GuzzleHttp\Psr7;
+use GuzzleHttp\TransferStats;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * HTTP handler that uses PHP's HTTP stream wrapper.
+ */
+class StreamHandler
+{
+ private $lastHeaders = [];
+
+ /**
+ * Sends an HTTP request.
+ *
+ * @param RequestInterface $request Request to send.
+ * @param array $options Request transfer options.
+ *
+ * @return PromiseInterface
+ */
+ public function __invoke(RequestInterface $request, array $options)
+ {
+ // Sleep if there is a delay specified.
+ if (isset($options['delay'])) {
+ usleep($options['delay'] * 1000);
+ }
+
+ $startTime = isset($options['on_stats']) ? microtime(true) : null;
+
+ try {
+ // Does not support the expect header.
+ $request = $request->withoutHeader('Expect');
+
+ // Append a content-length header if body size is zero to match
+ // cURL's behavior.
+ if (0 === $request->getBody()->getSize()) {
+ $request = $request->withHeader('Content-Length', 0);
+ }
+
+ return $this->createResponse(
+ $request,
+ $options,
+ $this->createStream($request, $options),
+ $startTime
+ );
+ } catch (\InvalidArgumentException $e) {
+ throw $e;
+ } catch (\Exception $e) {
+ // Determine if the error was a networking error.
+ $message = $e->getMessage();
+ // This list can probably get more comprehensive.
+ if (strpos($message, 'getaddrinfo') // DNS lookup failed
+ || strpos($message, 'Connection refused')
+ || strpos($message, "couldn't connect to host") // error on HHVM
+ ) {
+ $e = new ConnectException($e->getMessage(), $request, $e);
+ }
+ $e = RequestException::wrapException($request, $e);
+ $this->invokeStats($options, $request, $startTime, null, $e);
+
+ return new RejectedPromise($e);
+ }
+ }
+
+ private function invokeStats(
+ array $options,
+ RequestInterface $request,
+ $startTime,
+ ResponseInterface $response = null,
+ $error = null
+ ) {
+ if (isset($options['on_stats'])) {
+ $stats = new TransferStats(
+ $request,
+ $response,
+ microtime(true) - $startTime,
+ $error,
+ []
+ );
+ call_user_func($options['on_stats'], $stats);
+ }
+ }
+
+ private function createResponse(
+ RequestInterface $request,
+ array $options,
+ $stream,
+ $startTime
+ ) {
+ $hdrs = $this->lastHeaders;
+ $this->lastHeaders = [];
+ $parts = explode(' ', array_shift($hdrs), 3);
+ $ver = explode('/', $parts[0])[1];
+ $status = $parts[1];
+ $reason = isset($parts[2]) ? $parts[2] : null;
+ $headers = \GuzzleHttp\headers_from_lines($hdrs);
+ list ($stream, $headers) = $this->checkDecode($options, $headers, $stream);
+ $stream = Psr7\stream_for($stream);
+ $sink = $this->createSink($stream, $options);
+ $response = new Psr7\Response($status, $headers, $sink, $ver, $reason);
+
+ if (isset($options['on_headers'])) {
+ try {
+ $options['on_headers']($response);
+ } catch (\Exception $e) {
+ $msg = 'An error was encountered during the on_headers event';
+ $ex = new RequestException($msg, $request, $response, $e);
+ return new RejectedPromise($ex);
+ }
+ }
+
+ if ($sink !== $stream) {
+ $this->drain($stream, $sink);
+ }
+
+ $this->invokeStats($options, $request, $startTime, $response, null);
+
+ return new FulfilledPromise($response);
+ }
+
+ private function createSink(StreamInterface $stream, array $options)
+ {
+ if (!empty($options['stream'])) {
+ return $stream;
+ }
+
+ $sink = isset($options['sink'])
+ ? $options['sink']
+ : fopen('php://temp', 'r+');
+
+ return is_string($sink)
+ ? new Psr7\Stream(Psr7\try_fopen($sink, 'r+'))
+ : Psr7\stream_for($sink);
+ }
+
+ private function checkDecode(array $options, array $headers, $stream)
+ {
+ // Automatically decode responses when instructed.
+ if (!empty($options['decode_content'])) {
+ $normalizedKeys = \GuzzleHttp\normalize_header_keys($headers);
+ if (isset($normalizedKeys['content-encoding'])) {
+ $encoding = $headers[$normalizedKeys['content-encoding']];
+ if ($encoding[0] == 'gzip' || $encoding[0] == 'deflate') {
+ $stream = new Psr7\InflateStream(
+ Psr7\stream_for($stream)
+ );
+ // Remove content-encoding header
+ unset($headers[$normalizedKeys['content-encoding']]);
+ // Fix content-length header
+ if (isset($normalizedKeys['content-length'])) {
+ $length = (int) $stream->getSize();
+ if ($length == 0) {
+ unset($headers[$normalizedKeys['content-length']]);
+ } else {
+ $headers[$normalizedKeys['content-length']] = [$length];
+ }
+ }
+ }
+ }
+ }
+
+ return [$stream, $headers];
+ }
+
+ /**
+ * Drains the source stream into the "sink" client option.
+ *
+ * @param StreamInterface $source
+ * @param StreamInterface $sink
+ *
+ * @return StreamInterface
+ * @throws \RuntimeException when the sink option is invalid.
+ */
+ private function drain(StreamInterface $source, StreamInterface $sink)
+ {
+ Psr7\copy_to_stream($source, $sink);
+ $sink->seek(0);
+ $source->close();
+
+ return $sink;
+ }
+
+ /**
+ * Create a resource and check to ensure it was created successfully
+ *
+ * @param callable $callback Callable that returns stream resource
+ *
+ * @return resource
+ * @throws \RuntimeException on error
+ */
+ private function createResource(callable $callback)
+ {
+ $errors = null;
+ set_error_handler(function ($_, $msg, $file, $line) use (&$errors) {
+ $errors[] = [
+ 'message' => $msg,
+ 'file' => $file,
+ 'line' => $line
+ ];
+ return true;
+ });
+
+ $resource = $callback();
+ restore_error_handler();
+
+ if (!$resource) {
+ $message = 'Error creating resource: ';
+ foreach ($errors as $err) {
+ foreach ($err as $key => $value) {
+ $message .= "[$key] $value" . PHP_EOL;
+ }
+ }
+ throw new \RuntimeException(trim($message));
+ }
+
+ return $resource;
+ }
+
+ private function createStream(RequestInterface $request, array $options)
+ {
+ static $methods;
+ if (!$methods) {
+ $methods = array_flip(get_class_methods(__CLASS__));
+ }
+
+ // HTTP/1.1 streams using the PHP stream wrapper require a
+ // Connection: close header
+ if ($request->getProtocolVersion() == '1.1'
+ && !$request->hasHeader('Connection')
+ ) {
+ $request = $request->withHeader('Connection', 'close');
+ }
+
+ // Ensure SSL is verified by default
+ if (!isset($options['verify'])) {
+ $options['verify'] = true;
+ }
+
+ $params = [];
+ $context = $this->getDefaultContext($request, $options);
+
+ if (isset($options['on_headers']) && !is_callable($options['on_headers'])) {
+ throw new \InvalidArgumentException('on_headers must be callable');
+ }
+
+ if (!empty($options)) {
+ foreach ($options as $key => $value) {
+ $method = "add_{$key}";
+ if (isset($methods[$method])) {
+ $this->{$method}($request, $context, $value, $params);
+ }
+ }
+ }
+
+ if (isset($options['stream_context'])) {
+ if (!is_array($options['stream_context'])) {
+ throw new \InvalidArgumentException('stream_context must be an array');
+ }
+ $context = array_replace_recursive(
+ $context,
+ $options['stream_context']
+ );
+ }
+
+ $context = $this->createResource(
+ function () use ($context, $params) {
+ return stream_context_create($context, $params);
+ }
+ );
+
+ return $this->createResource(
+ function () use ($request, &$http_response_header, $context) {
+ $resource = fopen($request->getUri(), 'r', null, $context);
+ $this->lastHeaders = $http_response_header;
+ return $resource;
+ }
+ );
+ }
+
+ private function getDefaultContext(RequestInterface $request)
+ {
+ $headers = '';
+ foreach ($request->getHeaders() as $name => $value) {
+ foreach ($value as $val) {
+ $headers .= "$name: $val\r\n";
+ }
+ }
+
+ $context = [
+ 'http' => [
+ 'method' => $request->getMethod(),
+ 'header' => $headers,
+ 'protocol_version' => $request->getProtocolVersion(),
+ 'ignore_errors' => true,
+ 'follow_location' => 0,
+ ],
+ ];
+
+ $body = (string) $request->getBody();
+
+ if (!empty($body)) {
+ $context['http']['content'] = $body;
+ // Prevent the HTTP handler from adding a Content-Type header.
+ if (!$request->hasHeader('Content-Type')) {
+ $context['http']['header'] .= "Content-Type:\r\n";
+ }
+ }
+
+ $context['http']['header'] = rtrim($context['http']['header']);
+
+ return $context;
+ }
+
+ private function add_proxy(RequestInterface $request, &$options, $value, &$params)
+ {
+ if (!is_array($value)) {
+ $options['http']['proxy'] = $value;
+ } else {
+ $scheme = $request->getUri()->getScheme();
+ if (isset($value[$scheme])) {
+ if (!isset($value['no'])
+ || !\GuzzleHttp\is_host_in_noproxy(
+ $request->getUri()->getHost(),
+ $value['no']
+ )
+ ) {
+ $options['http']['proxy'] = $value[$scheme];
+ }
+ }
+ }
+ }
+
+ private function add_timeout(RequestInterface $request, &$options, $value, &$params)
+ {
+ $options['http']['timeout'] = $value;
+ }
+
+ private function add_verify(RequestInterface $request, &$options, $value, &$params)
+ {
+ if ($value === true) {
+ // PHP 5.6 or greater will find the system cert by default. When
+ // < 5.6, use the Guzzle bundled cacert.
+ if (PHP_VERSION_ID < 50600) {
+ $options['ssl']['cafile'] = \GuzzleHttp\default_ca_bundle();
+ }
+ } elseif (is_string($value)) {
+ $options['ssl']['cafile'] = $value;
+ if (!file_exists($value)) {
+ throw new \RuntimeException("SSL CA bundle not found: $value");
+ }
+ } elseif ($value === false) {
+ $options['ssl']['verify_peer'] = false;
+ $options['ssl']['verify_peer_name'] = false;
+ return;
+ } else {
+ throw new \InvalidArgumentException('Invalid verify request option');
+ }
+
+ $options['ssl']['verify_peer'] = true;
+ $options['ssl']['verify_peer_name'] = true;
+ $options['ssl']['allow_self_signed'] = false;
+ }
+
+ private function add_cert(RequestInterface $request, &$options, $value, &$params)
+ {
+ if (is_array($value)) {
+ $options['ssl']['passphrase'] = $value[1];
+ $value = $value[0];
+ }
+
+ if (!file_exists($value)) {
+ throw new \RuntimeException("SSL certificate not found: {$value}");
+ }
+
+ $options['ssl']['local_cert'] = $value;
+ }
+
+ private function add_progress(RequestInterface $request, &$options, $value, &$params)
+ {
+ $this->addNotification(
+ $params,
+ function ($code, $a, $b, $c, $transferred, $total) use ($value) {
+ if ($code == STREAM_NOTIFY_PROGRESS) {
+ $value($total, $transferred, null, null);
+ }
+ }
+ );
+ }
+
+ private function add_debug(RequestInterface $request, &$options, $value, &$params)
+ {
+ if ($value === false) {
+ return;
+ }
+
+ static $map = [
+ STREAM_NOTIFY_CONNECT => 'CONNECT',
+ STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED',
+ STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT',
+ STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS',
+ STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS',
+ STREAM_NOTIFY_REDIRECTED => 'REDIRECTED',
+ STREAM_NOTIFY_PROGRESS => 'PROGRESS',
+ STREAM_NOTIFY_FAILURE => 'FAILURE',
+ STREAM_NOTIFY_COMPLETED => 'COMPLETED',
+ STREAM_NOTIFY_RESOLVE => 'RESOLVE',
+ ];
+ static $args = ['severity', 'message', 'message_code',
+ 'bytes_transferred', 'bytes_max'];
+
+ $value = \GuzzleHttp\debug_resource($value);
+ $ident = $request->getMethod() . ' ' . $request->getUri();
+ $this->addNotification(
+ $params,
+ function () use ($ident, $value, $map, $args) {
+ $passed = func_get_args();
+ $code = array_shift($passed);
+ fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
+ foreach (array_filter($passed) as $i => $v) {
+ fwrite($value, $args[$i] . ': "' . $v . '" ');
+ }
+ fwrite($value, "\n");
+ }
+ );
+ }
+
+ private function addNotification(array &$params, callable $notify)
+ {
+ // Wrap the existing function if needed.
+ if (!isset($params['notification'])) {
+ $params['notification'] = $notify;
+ } else {
+ $params['notification'] = $this->callArray([
+ $params['notification'],
+ $notify
+ ]);
+ }
+ }
+
+ private function callArray(array $functions)
+ {
+ return function () use ($functions) {
+ $args = func_get_args();
+ foreach ($functions as $fn) {
+ call_user_func_array($fn, $args);
+ }
+ };
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/HandlerStack.php b/server/vendor/guzzlehttp/guzzle/src/HandlerStack.php
new file mode 100644
index 0000000..a72e38a
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/HandlerStack.php
@@ -0,0 +1,273 @@
+<?php
+namespace GuzzleHttp;
+
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Creates a composed Guzzle handler function by stacking middlewares on top of
+ * an HTTP handler function.
+ */
+class HandlerStack
+{
+ /** @var callable */
+ private $handler;
+
+ /** @var array */
+ private $stack = [];
+
+ /** @var callable|null */
+ private $cached;
+
+ /**
+ * Creates a default handler stack that can be used by clients.
+ *
+ * The returned handler will wrap the provided handler or use the most
+ * appropriate default handler for you system. The returned HandlerStack has
+ * support for cookies, redirects, HTTP error exceptions, and preparing a body
+ * before sending.
+ *
+ * The returned handler stack can be passed to a client in the "handler"
+ * option.
+ *
+ * @param callable $handler HTTP handler function to use with the stack. If no
+ * handler is provided, the best handler for your
+ * system will be utilized.
+ *
+ * @return HandlerStack
+ */
+ public static function create(callable $handler = null)
+ {
+ $stack = new self($handler ?: choose_handler());
+ $stack->push(Middleware::httpErrors(), 'http_errors');
+ $stack->push(Middleware::redirect(), 'allow_redirects');
+ $stack->push(Middleware::cookies(), 'cookies');
+ $stack->push(Middleware::prepareBody(), 'prepare_body');
+
+ return $stack;
+ }
+
+ /**
+ * @param callable $handler Underlying HTTP handler.
+ */
+ public function __construct(callable $handler = null)
+ {
+ $this->handler = $handler;
+ }
+
+ /**
+ * Invokes the handler stack as a composed handler
+ *
+ * @param RequestInterface $request
+ * @param array $options
+ */
+ public function __invoke(RequestInterface $request, array $options)
+ {
+ $handler = $this->resolve();
+
+ return $handler($request, $options);
+ }
+
+ /**
+ * Dumps a string representation of the stack.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ $depth = 0;
+ $stack = [];
+ if ($this->handler) {
+ $stack[] = "0) Handler: " . $this->debugCallable($this->handler);
+ }
+
+ $result = '';
+ foreach (array_reverse($this->stack) as $tuple) {
+ $depth++;
+ $str = "{$depth}) Name: '{$tuple[1]}', ";
+ $str .= "Function: " . $this->debugCallable($tuple[0]);
+ $result = "> {$str}\n{$result}";
+ $stack[] = $str;
+ }
+
+ foreach (array_keys($stack) as $k) {
+ $result .= "< {$stack[$k]}\n";
+ }
+
+ return $result;
+ }
+
+ /**
+ * Set the HTTP handler that actually returns a promise.
+ *
+ * @param callable $handler Accepts a request and array of options and
+ * returns a Promise.
+ */
+ public function setHandler(callable $handler)
+ {
+ $this->handler = $handler;
+ $this->cached = null;
+ }
+
+ /**
+ * Returns true if the builder has a handler.
+ *
+ * @return bool
+ */
+ public function hasHandler()
+ {
+ return (bool) $this->handler;
+ }
+
+ /**
+ * Unshift a middleware to the bottom of the stack.
+ *
+ * @param callable $middleware Middleware function
+ * @param string $name Name to register for this middleware.
+ */
+ public function unshift(callable $middleware, $name = null)
+ {
+ array_unshift($this->stack, [$middleware, $name]);
+ $this->cached = null;
+ }
+
+ /**
+ * Push a middleware to the top of the stack.
+ *
+ * @param callable $middleware Middleware function
+ * @param string $name Name to register for this middleware.
+ */
+ public function push(callable $middleware, $name = '')
+ {
+ $this->stack[] = [$middleware, $name];
+ $this->cached = null;
+ }
+
+ /**
+ * Add a middleware before another middleware by name.
+ *
+ * @param string $findName Middleware to find
+ * @param callable $middleware Middleware function
+ * @param string $withName Name to register for this middleware.
+ */
+ public function before($findName, callable $middleware, $withName = '')
+ {
+ $this->splice($findName, $withName, $middleware, true);
+ }
+
+ /**
+ * Add a middleware after another middleware by name.
+ *
+ * @param string $findName Middleware to find
+ * @param callable $middleware Middleware function
+ * @param string $withName Name to register for this middleware.
+ */
+ public function after($findName, callable $middleware, $withName = '')
+ {
+ $this->splice($findName, $withName, $middleware, false);
+ }
+
+ /**
+ * Remove a middleware by instance or name from the stack.
+ *
+ * @param callable|string $remove Middleware to remove by instance or name.
+ */
+ public function remove($remove)
+ {
+ $this->cached = null;
+ $idx = is_callable($remove) ? 0 : 1;
+ $this->stack = array_values(array_filter(
+ $this->stack,
+ function ($tuple) use ($idx, $remove) {
+ return $tuple[$idx] !== $remove;
+ }
+ ));
+ }
+
+ /**
+ * Compose the middleware and handler into a single callable function.
+ *
+ * @return callable
+ */
+ public function resolve()
+ {
+ if (!$this->cached) {
+ if (!($prev = $this->handler)) {
+ throw new \LogicException('No handler has been specified');
+ }
+
+ foreach (array_reverse($this->stack) as $fn) {
+ $prev = $fn[0]($prev);
+ }
+
+ $this->cached = $prev;
+ }
+
+ return $this->cached;
+ }
+
+ /**
+ * @param $name
+ * @return int
+ */
+ private function findByName($name)
+ {
+ foreach ($this->stack as $k => $v) {
+ if ($v[1] === $name) {
+ return $k;
+ }
+ }
+
+ throw new \InvalidArgumentException("Middleware not found: $name");
+ }
+
+ /**
+ * Splices a function into the middleware list at a specific position.
+ *
+ * @param $findName
+ * @param $withName
+ * @param callable $middleware
+ * @param $before
+ */
+ private function splice($findName, $withName, callable $middleware, $before)
+ {
+ $this->cached = null;
+ $idx = $this->findByName($findName);
+ $tuple = [$middleware, $withName];
+
+ if ($before) {
+ if ($idx === 0) {
+ array_unshift($this->stack, $tuple);
+ } else {
+ $replacement = [$tuple, $this->stack[$idx]];
+ array_splice($this->stack, $idx, 1, $replacement);
+ }
+ } elseif ($idx === count($this->stack) - 1) {
+ $this->stack[] = $tuple;
+ } else {
+ $replacement = [$this->stack[$idx], $tuple];
+ array_splice($this->stack, $idx, 1, $replacement);
+ }
+ }
+
+ /**
+ * Provides a debug string for a given callable.
+ *
+ * @param array|callable $fn Function to write as a string.
+ *
+ * @return string
+ */
+ private function debugCallable($fn)
+ {
+ if (is_string($fn)) {
+ return "callable({$fn})";
+ }
+
+ if (is_array($fn)) {
+ return is_string($fn[0])
+ ? "callable({$fn[0]}::{$fn[1]})"
+ : "callable(['" . get_class($fn[0]) . "', '{$fn[1]}'])";
+ }
+
+ return 'callable(' . spl_object_hash($fn) . ')';
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/MessageFormatter.php b/server/vendor/guzzlehttp/guzzle/src/MessageFormatter.php
new file mode 100644
index 0000000..6b090a9
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/MessageFormatter.php
@@ -0,0 +1,182 @@
+<?php
+namespace GuzzleHttp;
+
+use Psr\Http\Message\MessageInterface;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Formats log messages using variable substitutions for requests, responses,
+ * and other transactional data.
+ *
+ * The following variable substitutions are supported:
+ *
+ * - {request}: Full HTTP request message
+ * - {response}: Full HTTP response message
+ * - {ts}: ISO 8601 date in GMT
+ * - {date_iso_8601} ISO 8601 date in GMT
+ * - {date_common_log} Apache common log date using the configured timezone.
+ * - {host}: Host of the request
+ * - {method}: Method of the request
+ * - {uri}: URI of the request
+ * - {host}: Host of the request
+ * - {version}: Protocol version
+ * - {target}: Request target of the request (path + query + fragment)
+ * - {hostname}: Hostname of the machine that sent the request
+ * - {code}: Status code of the response (if available)
+ * - {phrase}: Reason phrase of the response (if available)
+ * - {error}: Any error messages (if available)
+ * - {req_header_*}: Replace `*` with the lowercased name of a request header to add to the message
+ * - {res_header_*}: Replace `*` with the lowercased name of a response header to add to the message
+ * - {req_headers}: Request headers
+ * - {res_headers}: Response headers
+ * - {req_body}: Request body
+ * - {res_body}: Response body
+ */
+class MessageFormatter
+{
+ /**
+ * Apache Common Log Format.
+ * @link http://httpd.apache.org/docs/2.4/logs.html#common
+ * @var string
+ */
+ const CLF = "{hostname} {req_header_User-Agent} - [{date_common_log}] \"{method} {target} HTTP/{version}\" {code} {res_header_Content-Length}";
+ const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
+ const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}';
+
+ /** @var string Template used to format log messages */
+ private $template;
+
+ /**
+ * @param string $template Log message template
+ */
+ public function __construct($template = self::CLF)
+ {
+ $this->template = $template ?: self::CLF;
+ }
+
+ /**
+ * Returns a formatted message string.
+ *
+ * @param RequestInterface $request Request that was sent
+ * @param ResponseInterface $response Response that was received
+ * @param \Exception $error Exception that was received
+ *
+ * @return string
+ */
+ public function format(
+ RequestInterface $request,
+ ResponseInterface $response = null,
+ \Exception $error = null
+ ) {
+ $cache = [];
+
+ return preg_replace_callback(
+ '/{\s*([A-Za-z_\-\.0-9]+)\s*}/',
+ function (array $matches) use ($request, $response, $error, &$cache) {
+
+ if (isset($cache[$matches[1]])) {
+ return $cache[$matches[1]];
+ }
+
+ $result = '';
+ switch ($matches[1]) {
+ case 'request':
+ $result = Psr7\str($request);
+ break;
+ case 'response':
+ $result = $response ? Psr7\str($response) : '';
+ break;
+ case 'req_headers':
+ $result = trim($request->getMethod()
+ . ' ' . $request->getRequestTarget())
+ . ' HTTP/' . $request->getProtocolVersion() . "\r\n"
+ . $this->headers($request);
+ break;
+ case 'res_headers':
+ $result = $response ?
+ sprintf(
+ 'HTTP/%s %d %s',
+ $response->getProtocolVersion(),
+ $response->getStatusCode(),
+ $response->getReasonPhrase()
+ ) . "\r\n" . $this->headers($response)
+ : 'NULL';
+ break;
+ case 'req_body':
+ $result = $request->getBody();
+ break;
+ case 'res_body':
+ $result = $response ? $response->getBody() : 'NULL';
+ break;
+ case 'ts':
+ case 'date_iso_8601':
+ $result = gmdate('c');
+ break;
+ case 'date_common_log':
+ $result = date('d/M/Y:H:i:s O');
+ break;
+ case 'method':
+ $result = $request->getMethod();
+ break;
+ case 'version':
+ $result = $request->getProtocolVersion();
+ break;
+ case 'uri':
+ case 'url':
+ $result = $request->getUri();
+ break;
+ case 'target':
+ $result = $request->getRequestTarget();
+ break;
+ case 'req_version':
+ $result = $request->getProtocolVersion();
+ break;
+ case 'res_version':
+ $result = $response
+ ? $response->getProtocolVersion()
+ : 'NULL';
+ break;
+ case 'host':
+ $result = $request->getHeaderLine('Host');
+ break;
+ case 'hostname':
+ $result = gethostname();
+ break;
+ case 'code':
+ $result = $response ? $response->getStatusCode() : 'NULL';
+ break;
+ case 'phrase':
+ $result = $response ? $response->getReasonPhrase() : 'NULL';
+ break;
+ case 'error':
+ $result = $error ? $error->getMessage() : 'NULL';
+ break;
+ default:
+ // handle prefixed dynamic headers
+ if (strpos($matches[1], 'req_header_') === 0) {
+ $result = $request->getHeaderLine(substr($matches[1], 11));
+ } elseif (strpos($matches[1], 'res_header_') === 0) {
+ $result = $response
+ ? $response->getHeaderLine(substr($matches[1], 11))
+ : 'NULL';
+ }
+ }
+
+ $cache[$matches[1]] = $result;
+ return $result;
+ },
+ $this->template
+ );
+ }
+
+ private function headers(MessageInterface $message)
+ {
+ $result = '';
+ foreach ($message->getHeaders() as $name => $values) {
+ $result .= $name . ': ' . implode(', ', $values) . "\r\n";
+ }
+
+ return trim($result);
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Middleware.php b/server/vendor/guzzlehttp/guzzle/src/Middleware.php
new file mode 100644
index 0000000..85d3165
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Middleware.php
@@ -0,0 +1,249 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Cookie\CookieJarInterface;
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Promise\RejectedPromise;
+use GuzzleHttp\Psr7;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Log\LoggerInterface;
+use Psr\Log\LogLevel;
+
+/**
+ * Functions used to create and wrap handlers with handler middleware.
+ */
+final class Middleware
+{
+ /**
+ * Middleware that adds cookies to requests.
+ *
+ * The options array must be set to a CookieJarInterface in order to use
+ * cookies. This is typically handled for you by a client.
+ *
+ * @return callable Returns a function that accepts the next handler.
+ */
+ public static function cookies()
+ {
+ return function (callable $handler) {
+ return function ($request, array $options) use ($handler) {
+ if (empty($options['cookies'])) {
+ return $handler($request, $options);
+ } elseif (!($options['cookies'] instanceof CookieJarInterface)) {
+ throw new \InvalidArgumentException('cookies must be an instance of GuzzleHttp\Cookie\CookieJarInterface');
+ }
+ $cookieJar = $options['cookies'];
+ $request = $cookieJar->withCookieHeader($request);
+ return $handler($request, $options)
+ ->then(function ($response) use ($cookieJar, $request) {
+ $cookieJar->extractCookies($request, $response);
+ return $response;
+ }
+ );
+ };
+ };
+ }
+
+ /**
+ * Middleware that throws exceptions for 4xx or 5xx responses when the
+ * "http_error" request option is set to true.
+ *
+ * @return callable Returns a function that accepts the next handler.
+ */
+ public static function httpErrors()
+ {
+ return function (callable $handler) {
+ return function ($request, array $options) use ($handler) {
+ if (empty($options['http_errors'])) {
+ return $handler($request, $options);
+ }
+ return $handler($request, $options)->then(
+ function (ResponseInterface $response) use ($request, $handler) {
+ $code = $response->getStatusCode();
+ if ($code < 400) {
+ return $response;
+ }
+ throw RequestException::create($request, $response);
+ }
+ );
+ };
+ };
+ }
+
+ /**
+ * Middleware that pushes history data to an ArrayAccess container.
+ *
+ * @param array $container Container to hold the history (by reference).
+ *
+ * @return callable Returns a function that accepts the next handler.
+ */
+ public static function history(array &$container)
+ {
+ return function (callable $handler) use (&$container) {
+ return function ($request, array $options) use ($handler, &$container) {
+ return $handler($request, $options)->then(
+ function ($value) use ($request, &$container, $options) {
+ $container[] = [
+ 'request' => $request,
+ 'response' => $value,
+ 'error' => null,
+ 'options' => $options
+ ];
+ return $value;
+ },
+ function ($reason) use ($request, &$container, $options) {
+ $container[] = [
+ 'request' => $request,
+ 'response' => null,
+ 'error' => $reason,
+ 'options' => $options
+ ];
+ return new RejectedPromise($reason);
+ }
+ );
+ };
+ };
+ }
+
+ /**
+ * Middleware that invokes a callback before and after sending a request.
+ *
+ * The provided listener cannot modify or alter the response. It simply
+ * "taps" into the chain to be notified before returning the promise. The
+ * before listener accepts a request and options array, and the after
+ * listener accepts a request, options array, and response promise.
+ *
+ * @param callable $before Function to invoke before forwarding the request.
+ * @param callable $after Function invoked after forwarding.
+ *
+ * @return callable Returns a function that accepts the next handler.
+ */
+ public static function tap(callable $before = null, callable $after = null)
+ {
+ return function (callable $handler) use ($before, $after) {
+ return function ($request, array $options) use ($handler, $before, $after) {
+ if ($before) {
+ $before($request, $options);
+ }
+ $response = $handler($request, $options);
+ if ($after) {
+ $after($request, $options, $response);
+ }
+ return $response;
+ };
+ };
+ }
+
+ /**
+ * Middleware that handles request redirects.
+ *
+ * @return callable Returns a function that accepts the next handler.
+ */
+ public static function redirect()
+ {
+ return function (callable $handler) {
+ return new RedirectMiddleware($handler);
+ };
+ }
+
+ /**
+ * Middleware that retries requests based on the boolean result of
+ * invoking the provided "decider" function.
+ *
+ * If no delay function is provided, a simple implementation of exponential
+ * backoff will be utilized.
+ *
+ * @param callable $decider Function that accepts the number of retries,
+ * a request, [response], and [exception] and
+ * returns true if the request is to be retried.
+ * @param callable $delay Function that accepts the number of retries and
+ * returns the number of milliseconds to delay.
+ *
+ * @return callable Returns a function that accepts the next handler.
+ */
+ public static function retry(callable $decider, callable $delay = null)
+ {
+ return function (callable $handler) use ($decider, $delay) {
+ return new RetryMiddleware($decider, $handler, $delay);
+ };
+ }
+
+ /**
+ * Middleware that logs requests, responses, and errors using a message
+ * formatter.
+ *
+ * @param LoggerInterface $logger Logs messages.
+ * @param MessageFormatter $formatter Formatter used to create message strings.
+ * @param string $logLevel Level at which to log requests.
+ *
+ * @return callable Returns a function that accepts the next handler.
+ */
+ public static function log(LoggerInterface $logger, MessageFormatter $formatter, $logLevel = LogLevel::INFO)
+ {
+ return function (callable $handler) use ($logger, $formatter, $logLevel) {
+ return function ($request, array $options) use ($handler, $logger, $formatter, $logLevel) {
+ return $handler($request, $options)->then(
+ function ($response) use ($logger, $request, $formatter, $logLevel) {
+ $message = $formatter->format($request, $response);
+ $logger->log($logLevel, $message);
+ return $response;
+ },
+ function ($reason) use ($logger, $request, $formatter) {
+ $response = $reason instanceof RequestException
+ ? $reason->getResponse()
+ : null;
+ $message = $formatter->format($request, $response, $reason);
+ $logger->notice($message);
+ return \GuzzleHttp\Promise\rejection_for($reason);
+ }
+ );
+ };
+ };
+ }
+
+ /**
+ * This middleware adds a default content-type if possible, a default
+ * content-length or transfer-encoding header, and the expect header.
+ *
+ * @return callable
+ */
+ public static function prepareBody()
+ {
+ return function (callable $handler) {
+ return new PrepareBodyMiddleware($handler);
+ };
+ }
+
+ /**
+ * Middleware that applies a map function to the request before passing to
+ * the next handler.
+ *
+ * @param callable $fn Function that accepts a RequestInterface and returns
+ * a RequestInterface.
+ * @return callable
+ */
+ public static function mapRequest(callable $fn)
+ {
+ return function (callable $handler) use ($fn) {
+ return function ($request, array $options) use ($handler, $fn) {
+ return $handler($fn($request), $options);
+ };
+ };
+ }
+
+ /**
+ * Middleware that applies a map function to the resolved promise's
+ * response.
+ *
+ * @param callable $fn Function that accepts a ResponseInterface and
+ * returns a ResponseInterface.
+ * @return callable
+ */
+ public static function mapResponse(callable $fn)
+ {
+ return function (callable $handler) use ($fn) {
+ return function ($request, array $options) use ($handler, $fn) {
+ return $handler($request, $options)->then($fn);
+ };
+ };
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/Pool.php b/server/vendor/guzzlehttp/guzzle/src/Pool.php
new file mode 100644
index 0000000..8f1be33
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/Pool.php
@@ -0,0 +1,123 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Promise\PromisorInterface;
+use Psr\Http\Message\RequestInterface;
+use GuzzleHttp\Promise\EachPromise;
+
+/**
+ * Sends and iterator of requests concurrently using a capped pool size.
+ *
+ * The pool will read from an iterator until it is cancelled or until the
+ * iterator is consumed. When a request is yielded, the request is sent after
+ * applying the "request_options" request options (if provided in the ctor).
+ *
+ * When a function is yielded by the iterator, the function is provided the
+ * "request_options" array that should be merged on top of any existing
+ * options, and the function MUST then return a wait-able promise.
+ */
+class Pool implements PromisorInterface
+{
+ /** @var EachPromise */
+ private $each;
+
+ /**
+ * @param ClientInterface $client Client used to send the requests.
+ * @param array|\Iterator $requests Requests or functions that return
+ * requests to send concurrently.
+ * @param array $config Associative array of options
+ * - concurrency: (int) Maximum number of requests to send concurrently
+ * - options: Array of request options to apply to each request.
+ * - fulfilled: (callable) Function to invoke when a request completes.
+ * - rejected: (callable) Function to invoke when a request is rejected.
+ */
+ public function __construct(
+ ClientInterface $client,
+ $requests,
+ array $config = []
+ ) {
+ // Backwards compatibility.
+ if (isset($config['pool_size'])) {
+ $config['concurrency'] = $config['pool_size'];
+ } elseif (!isset($config['concurrency'])) {
+ $config['concurrency'] = 25;
+ }
+
+ if (isset($config['options'])) {
+ $opts = $config['options'];
+ unset($config['options']);
+ } else {
+ $opts = [];
+ }
+
+ $iterable = \GuzzleHttp\Promise\iter_for($requests);
+ $requests = function () use ($iterable, $client, $opts) {
+ foreach ($iterable as $key => $rfn) {
+ if ($rfn instanceof RequestInterface) {
+ yield $key => $client->sendAsync($rfn, $opts);
+ } elseif (is_callable($rfn)) {
+ yield $key => $rfn($opts);
+ } else {
+ throw new \InvalidArgumentException('Each value yielded by '
+ . 'the iterator must be a Psr7\Http\Message\RequestInterface '
+ . 'or a callable that returns a promise that fulfills '
+ . 'with a Psr7\Message\Http\ResponseInterface object.');
+ }
+ }
+ };
+
+ $this->each = new EachPromise($requests(), $config);
+ }
+
+ public function promise()
+ {
+ return $this->each->promise();
+ }
+
+ /**
+ * Sends multiple requests concurrently and returns an array of responses
+ * and exceptions that uses the same ordering as the provided requests.
+ *
+ * IMPORTANT: This method keeps every request and response in memory, and
+ * as such, is NOT recommended when sending a large number or an
+ * indeterminate number of requests concurrently.
+ *
+ * @param ClientInterface $client Client used to send the requests
+ * @param array|\Iterator $requests Requests to send concurrently.
+ * @param array $options Passes through the options available in
+ * {@see GuzzleHttp\Pool::__construct}
+ *
+ * @return array Returns an array containing the response or an exception
+ * in the same order that the requests were sent.
+ * @throws \InvalidArgumentException if the event format is incorrect.
+ */
+ public static function batch(
+ ClientInterface $client,
+ $requests,
+ array $options = []
+ ) {
+ $res = [];
+ self::cmpCallback($options, 'fulfilled', $res);
+ self::cmpCallback($options, 'rejected', $res);
+ $pool = new static($client, $requests, $options);
+ $pool->promise()->wait();
+ ksort($res);
+
+ return $res;
+ }
+
+ private static function cmpCallback(array &$options, $name, array &$results)
+ {
+ if (!isset($options[$name])) {
+ $options[$name] = function ($v, $k) use (&$results) {
+ $results[$k] = $v;
+ };
+ } else {
+ $currentFn = $options[$name];
+ $options[$name] = function ($v, $k) use (&$results, $currentFn) {
+ $currentFn($v, $k);
+ $results[$k] = $v;
+ };
+ }
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php b/server/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php
new file mode 100644
index 0000000..e6d176b
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php
@@ -0,0 +1,112 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Promise\PromiseInterface;
+use GuzzleHttp\Psr7;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Prepares requests that contain a body, adding the Content-Length,
+ * Content-Type, and Expect headers.
+ */
+class PrepareBodyMiddleware
+{
+ /** @var callable */
+ private $nextHandler;
+
+ /** @var array */
+ private static $skipMethods = ['GET' => true, 'HEAD' => true];
+
+ /**
+ * @param callable $nextHandler Next handler to invoke.
+ */
+ public function __construct(callable $nextHandler)
+ {
+ $this->nextHandler = $nextHandler;
+ }
+
+ /**
+ * @param RequestInterface $request
+ * @param array $options
+ *
+ * @return PromiseInterface
+ */
+ public function __invoke(RequestInterface $request, array $options)
+ {
+ $fn = $this->nextHandler;
+
+ // Don't do anything if the request has no body.
+ if (isset(self::$skipMethods[$request->getMethod()])
+ || $request->getBody()->getSize() === 0
+ ) {
+ return $fn($request, $options);
+ }
+
+ $modify = [];
+
+ // Add a default content-type if possible.
+ if (!$request->hasHeader('Content-Type')) {
+ if ($uri = $request->getBody()->getMetadata('uri')) {
+ if ($type = Psr7\mimetype_from_filename($uri)) {
+ $modify['set_headers']['Content-Type'] = $type;
+ }
+ }
+ }
+
+ // Add a default content-length or transfer-encoding header.
+ if (!isset(self::$skipMethods[$request->getMethod()])
+ && !$request->hasHeader('Content-Length')
+ && !$request->hasHeader('Transfer-Encoding')
+ ) {
+ $size = $request->getBody()->getSize();
+ if ($size !== null) {
+ $modify['set_headers']['Content-Length'] = $size;
+ } else {
+ $modify['set_headers']['Transfer-Encoding'] = 'chunked';
+ }
+ }
+
+ // Add the expect header if needed.
+ $this->addExpectHeader($request, $options, $modify);
+
+ return $fn(Psr7\modify_request($request, $modify), $options);
+ }
+
+ private function addExpectHeader(
+ RequestInterface $request,
+ array $options,
+ array &$modify
+ ) {
+ // Determine if the Expect header should be used
+ if ($request->hasHeader('Expect')) {
+ return;
+ }
+
+ $expect = isset($options['expect']) ? $options['expect'] : null;
+
+ // Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0
+ if ($expect === false || $request->getProtocolVersion() < 1.1) {
+ return;
+ }
+
+ // The expect header is unconditionally enabled
+ if ($expect === true) {
+ $modify['set_headers']['Expect'] = '100-Continue';
+ return;
+ }
+
+ // By default, send the expect header when the payload is > 1mb
+ if ($expect === null) {
+ $expect = 1048576;
+ }
+
+ // Always add if the body cannot be rewound, the size cannot be
+ // determined, or the size is greater than the cutoff threshold
+ $body = $request->getBody();
+ $size = $body->getSize();
+
+ if ($size === null || $size >= (int) $expect || !$body->isSeekable()) {
+ $modify['set_headers']['Expect'] = '100-Continue';
+ }
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php b/server/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php
new file mode 100644
index 0000000..dbe8b87
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php
@@ -0,0 +1,231 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Exception\BadResponseException;
+use GuzzleHttp\Exception\TooManyRedirectsException;
+use GuzzleHttp\Promise\PromiseInterface;
+use GuzzleHttp\Psr7;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\UriInterface;
+
+/**
+ * Request redirect middleware.
+ *
+ * Apply this middleware like other middleware using
+ * {@see GuzzleHttp\Middleware::redirect()}.
+ */
+class RedirectMiddleware
+{
+ const HISTORY_HEADER = 'X-Guzzle-Redirect-History';
+
+ public static $defaultSettings = [
+ 'max' => 5,
+ 'protocols' => ['http', 'https'],
+ 'strict' => false,
+ 'referer' => false,
+ 'track_redirects' => false,
+ ];
+
+ /** @var callable */
+ private $nextHandler;
+
+ /**
+ * @param callable $nextHandler Next handler to invoke.
+ */
+ public function __construct(callable $nextHandler)
+ {
+ $this->nextHandler = $nextHandler;
+ }
+
+ /**
+ * @param RequestInterface $request
+ * @param array $options
+ *
+ * @return PromiseInterface
+ */
+ public function __invoke(RequestInterface $request, array $options)
+ {
+ $fn = $this->nextHandler;
+
+ if (empty($options['allow_redirects'])) {
+ return $fn($request, $options);
+ }
+
+ if ($options['allow_redirects'] === true) {
+ $options['allow_redirects'] = self::$defaultSettings;
+ } elseif (!is_array($options['allow_redirects'])) {
+ throw new \InvalidArgumentException('allow_redirects must be true, false, or array');
+ } else {
+ // Merge the default settings with the provided settings
+ $options['allow_redirects'] += self::$defaultSettings;
+ }
+
+ if (empty($options['allow_redirects']['max'])) {
+ return $fn($request, $options);
+ }
+
+ return $fn($request, $options)
+ ->then(function (ResponseInterface $response) use ($request, $options) {
+ return $this->checkRedirect($request, $options, $response);
+ });
+ }
+
+ /**
+ * @param RequestInterface $request
+ * @param array $options
+ * @param ResponseInterface|PromiseInterface $response
+ *
+ * @return ResponseInterface|PromiseInterface
+ */
+ public function checkRedirect(
+ RequestInterface $request,
+ array $options,
+ ResponseInterface $response
+ ) {
+ if (substr($response->getStatusCode(), 0, 1) != '3'
+ || !$response->hasHeader('Location')
+ ) {
+ return $response;
+ }
+
+ $this->guardMax($request, $options);
+ $nextRequest = $this->modifyRequest($request, $options, $response);
+
+ if (isset($options['allow_redirects']['on_redirect'])) {
+ call_user_func(
+ $options['allow_redirects']['on_redirect'],
+ $request,
+ $response,
+ $nextRequest->getUri()
+ );
+ }
+
+ /** @var PromiseInterface|ResponseInterface $promise */
+ $promise = $this($nextRequest, $options);
+
+ // Add headers to be able to track history of redirects.
+ if (!empty($options['allow_redirects']['track_redirects'])) {
+ return $this->withTracking(
+ $promise,
+ (string) $nextRequest->getUri()
+ );
+ }
+
+ return $promise;
+ }
+
+ private function withTracking(PromiseInterface $promise, $uri)
+ {
+ return $promise->then(
+ function (ResponseInterface $response) use ($uri) {
+ // Note that we are pushing to the front of the list as this
+ // would be an earlier response than what is currently present
+ // in the history header.
+ $header = $response->getHeader(self::HISTORY_HEADER);
+ array_unshift($header, $uri);
+ return $response->withHeader(self::HISTORY_HEADER, $header);
+ }
+ );
+ }
+
+ private function guardMax(RequestInterface $request, array &$options)
+ {
+ $current = isset($options['__redirect_count'])
+ ? $options['__redirect_count']
+ : 0;
+ $options['__redirect_count'] = $current + 1;
+ $max = $options['allow_redirects']['max'];
+
+ if ($options['__redirect_count'] > $max) {
+ throw new TooManyRedirectsException(
+ "Will not follow more than {$max} redirects",
+ $request
+ );
+ }
+ }
+
+ /**
+ * @param RequestInterface $request
+ * @param array $options
+ * @param ResponseInterface $response
+ *
+ * @return RequestInterface
+ */
+ public function modifyRequest(
+ RequestInterface $request,
+ array $options,
+ ResponseInterface $response
+ ) {
+ // Request modifications to apply.
+ $modify = [];
+ $protocols = $options['allow_redirects']['protocols'];
+
+ // Use a GET request if this is an entity enclosing request and we are
+ // not forcing RFC compliance, but rather emulating what all browsers
+ // would do.
+ $statusCode = $response->getStatusCode();
+ if ($statusCode == 303 ||
+ ($statusCode <= 302 && $request->getBody() && !$options['allow_redirects']['strict'])
+ ) {
+ $modify['method'] = 'GET';
+ $modify['body'] = '';
+ }
+
+ $modify['uri'] = $this->redirectUri($request, $response, $protocols);
+ Psr7\rewind_body($request);
+
+ // Add the Referer header if it is told to do so and only
+ // add the header if we are not redirecting from https to http.
+ if ($options['allow_redirects']['referer']
+ && $modify['uri']->getScheme() === $request->getUri()->getScheme()
+ ) {
+ $uri = $request->getUri()->withUserInfo('', '');
+ $modify['set_headers']['Referer'] = (string) $uri;
+ } else {
+ $modify['remove_headers'][] = 'Referer';
+ }
+
+ // Remove Authorization header if host is different.
+ if ($request->getUri()->getHost() !== $modify['uri']->getHost()) {
+ $modify['remove_headers'][] = 'Authorization';
+ }
+
+ return Psr7\modify_request($request, $modify);
+ }
+
+ /**
+ * Set the appropriate URL on the request based on the location header
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $response
+ * @param array $protocols
+ *
+ * @return UriInterface
+ */
+ private function redirectUri(
+ RequestInterface $request,
+ ResponseInterface $response,
+ array $protocols
+ ) {
+ $location = Psr7\Uri::resolve(
+ $request->getUri(),
+ $response->getHeaderLine('Location')
+ );
+
+ // Ensure that the redirect URI is allowed based on the protocols.
+ if (!in_array($location->getScheme(), $protocols)) {
+ throw new BadResponseException(
+ sprintf(
+ 'Redirect URI, %s, does not use one of the allowed redirect protocols: %s',
+ $location,
+ implode(', ', $protocols)
+ ),
+ $request,
+ $response
+ );
+ }
+
+ return $location;
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/RequestOptions.php b/server/vendor/guzzlehttp/guzzle/src/RequestOptions.php
new file mode 100644
index 0000000..3af2f36
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/RequestOptions.php
@@ -0,0 +1,244 @@
+<?php
+namespace GuzzleHttp;
+
+/**
+ * This class contains a list of built-in Guzzle request options.
+ *
+ * More documentation for each option can be found at http://guzzlephp.org/.
+ *
+ * @link http://docs.guzzlephp.org/en/v6/request-options.html
+ */
+final class RequestOptions
+{
+ /**
+ * allow_redirects: (bool|array) Controls redirect behavior. Pass false
+ * to disable redirects, pass true to enable redirects, pass an
+ * associative to provide custom redirect settings. Defaults to "false".
+ * This option only works if your handler has the RedirectMiddleware. When
+ * passing an associative array, you can provide the following key value
+ * pairs:
+ *
+ * - max: (int, default=5) maximum number of allowed redirects.
+ * - strict: (bool, default=false) Set to true to use strict redirects
+ * meaning redirect POST requests with POST requests vs. doing what most
+ * browsers do which is redirect POST requests with GET requests
+ * - referer: (bool, default=true) Set to false to disable the Referer
+ * header.
+ * - protocols: (array, default=['http', 'https']) Allowed redirect
+ * protocols.
+ * - on_redirect: (callable) PHP callable that is invoked when a redirect
+ * is encountered. The callable is invoked with the request, the redirect
+ * response that was received, and the effective URI. Any return value
+ * from the on_redirect function is ignored.
+ */
+ const ALLOW_REDIRECTS = 'allow_redirects';
+
+ /**
+ * auth: (array) Pass an array of HTTP authentication parameters to use
+ * with the request. The array must contain the username in index [0],
+ * the password in index [1], and you can optionally provide a built-in
+ * authentication type in index [2]. Pass null to disable authentication
+ * for a request.
+ */
+ const AUTH = 'auth';
+
+ /**
+ * body: (string|null|callable|iterator|object) Body to send in the
+ * request.
+ */
+ const BODY = 'body';
+
+ /**
+ * cert: (string|array) Set to a string to specify the path to a file
+ * containing a PEM formatted SSL client side certificate. If a password
+ * is required, then set cert to an array containing the path to the PEM
+ * file in the first array element followed by the certificate password
+ * in the second array element.
+ */
+ const CERT = 'cert';
+
+ /**
+ * cookies: (bool|GuzzleHttp\Cookie\CookieJarInterface, default=false)
+ * Specifies whether or not cookies are used in a request or what cookie
+ * jar to use or what cookies to send. This option only works if your
+ * handler has the `cookie` middleware. Valid values are `false` and
+ * an instance of {@see GuzzleHttp\Cookie\CookieJarInterface}.
+ */
+ const COOKIES = 'cookies';
+
+ /**
+ * connect_timeout: (float, default=0) Float describing the number of
+ * seconds to wait while trying to connect to a server. Use 0 to wait
+ * indefinitely (the default behavior).
+ */
+ const CONNECT_TIMEOUT = 'connect_timeout';
+
+ /**
+ * debug: (bool|resource) Set to true or set to a PHP stream returned by
+ * fopen() enable debug output with the HTTP handler used to send a
+ * request.
+ */
+ const DEBUG = 'debug';
+
+ /**
+ * decode_content: (bool, default=true) Specify whether or not
+ * Content-Encoding responses (gzip, deflate, etc.) are automatically
+ * decoded.
+ */
+ const DECODE_CONTENT = 'decode_content';
+
+ /**
+ * delay: (int) The amount of time to delay before sending in milliseconds.
+ */
+ const DELAY = 'delay';
+
+ /**
+ * expect: (bool|integer) Controls the behavior of the
+ * "Expect: 100-Continue" header.
+ *
+ * Set to `true` to enable the "Expect: 100-Continue" header for all
+ * requests that sends a body. Set to `false` to disable the
+ * "Expect: 100-Continue" header for all requests. Set to a number so that
+ * the size of the payload must be greater than the number in order to send
+ * the Expect header. Setting to a number will send the Expect header for
+ * all requests in which the size of the payload cannot be determined or
+ * where the body is not rewindable.
+ *
+ * By default, Guzzle will add the "Expect: 100-Continue" header when the
+ * size of the body of a request is greater than 1 MB and a request is
+ * using HTTP/1.1.
+ */
+ const EXPECT = 'expect';
+
+ /**
+ * form_params: (array) Associative array of form field names to values
+ * where each value is a string or array of strings. Sets the Content-Type
+ * header to application/x-www-form-urlencoded when no Content-Type header
+ * is already present.
+ */
+ const FORM_PARAMS = 'form_params';
+
+ /**
+ * headers: (array) Associative array of HTTP headers. Each value MUST be
+ * a string or array of strings.
+ */
+ const HEADERS = 'headers';
+
+ /**
+ * http_errors: (bool, default=true) Set to false to disable exceptions
+ * when a non- successful HTTP response is received. By default,
+ * exceptions will be thrown for 4xx and 5xx responses. This option only
+ * works if your handler has the `httpErrors` middleware.
+ */
+ const HTTP_ERRORS = 'http_errors';
+
+ /**
+ * json: (mixed) Adds JSON data to a request. The provided value is JSON
+ * encoded and a Content-Type header of application/json will be added to
+ * the request if no Content-Type header is already present.
+ */
+ const JSON = 'json';
+
+ /**
+ * multipart: (array) 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. If no "filename" key is present, then no "filename" attribute
+ * will be added to the part.
+ */
+ const MULTIPART = 'multipart';
+
+ /**
+ * on_headers: (callable) A callable that is invoked when the HTTP headers
+ * of the response have been received but the body has not yet begun to
+ * download.
+ */
+ const ON_HEADERS = 'on_headers';
+
+ /**
+ * on_stats: (callable) allows you to get access to transfer statistics of
+ * a request and access the lower level transfer details of the handler
+ * associated with your client. ``on_stats`` is a callable that is invoked
+ * when a handler has finished sending a request. The callback is invoked
+ * with transfer statistics about the request, the response received, or
+ * the error encountered. Included in the data is the total amount of time
+ * taken to send the request.
+ */
+ const ON_STATS = 'on_stats';
+
+ /**
+ * progress: (callable) Defines a function to invoke when transfer
+ * progress is made. The function accepts the following positional
+ * arguments: the total number of bytes expected to be downloaded, the
+ * number of bytes downloaded so far, the number of bytes expected to be
+ * uploaded, the number of bytes uploaded so far.
+ */
+ const PROGRESS = 'progress';
+
+ /**
+ * proxy: (string|array) Pass a string to specify an HTTP proxy, or an
+ * array to specify different proxies for different protocols (where the
+ * key is the protocol and the value is a proxy string).
+ */
+ const PROXY = 'proxy';
+
+ /**
+ * query: (array|string) Associative array of query string values to add
+ * to the request. This option uses PHP's http_build_query() to create
+ * the string representation. Pass a string value if you need more
+ * control than what this method provides
+ */
+ const QUERY = 'query';
+
+ /**
+ * sink: (resource|string|StreamInterface) Where the data of the
+ * response is written to. Defaults to a PHP temp stream. Providing a
+ * string will write data to a file by the given name.
+ */
+ const SINK = 'sink';
+
+ /**
+ * synchronous: (bool) Set to true to inform HTTP handlers that you intend
+ * on waiting on the response. This can be useful for optimizations. Note
+ * that a promise is still returned if you are using one of the async
+ * client methods.
+ */
+ const SYNCHRONOUS = 'synchronous';
+
+ /**
+ * ssl_key: (array|string) Specify the path to a file containing a private
+ * SSL key in PEM format. If a password is required, then set to an array
+ * containing the path to the SSL key in the first array element followed
+ * by the password required for the certificate in the second element.
+ */
+ const SSL_KEY = 'ssl_key';
+
+ /**
+ * stream: Set to true to attempt to stream a response rather than
+ * download it all up-front.
+ */
+ const STREAM = 'stream';
+
+ /**
+ * verify: (bool|string, default=true) Describes the SSL certificate
+ * verification behavior of a request. Set to true to enable SSL
+ * certificate verification using the system CA bundle when available
+ * (the default). Set to false to disable certificate verification (this
+ * is insecure!). Set to a string to provide the path to a CA bundle on
+ * disk to enable verification using a custom certificate.
+ */
+ const VERIFY = 'verify';
+
+ /**
+ * timeout: (float, default=0) Float describing the timeout of the
+ * request in seconds. Use 0 to wait indefinitely (the default behavior).
+ */
+ const TIMEOUT = 'timeout';
+
+ /**
+ * version: (float) Specifies the HTTP protocol version to attempt to use.
+ */
+ const VERSION = 'version';
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/RetryMiddleware.php b/server/vendor/guzzlehttp/guzzle/src/RetryMiddleware.php
new file mode 100644
index 0000000..4b95a14
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/RetryMiddleware.php
@@ -0,0 +1,111 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Promise\PromiseInterface;
+use GuzzleHttp\Promise\RejectedPromise;
+use GuzzleHttp\Psr7;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * Middleware that retries requests based on the boolean result of
+ * invoking the provided "decider" function.
+ */
+class RetryMiddleware
+{
+ /** @var callable */
+ private $nextHandler;
+
+ /** @var callable */
+ private $decider;
+
+ /**
+ * @param callable $decider Function that accepts the number of retries,
+ * a request, [response], and [exception] and
+ * returns true if the request is to be
+ * retried.
+ * @param callable $nextHandler Next handler to invoke.
+ * @param callable $delay Function that accepts the number of retries
+ * and returns the number of milliseconds to
+ * delay.
+ */
+ public function __construct(
+ callable $decider,
+ callable $nextHandler,
+ callable $delay = null
+ ) {
+ $this->decider = $decider;
+ $this->nextHandler = $nextHandler;
+ $this->delay = $delay ?: __CLASS__ . '::exponentialDelay';
+ }
+
+ /**
+ * Default exponential backoff delay function.
+ *
+ * @param $retries
+ *
+ * @return int
+ */
+ public static function exponentialDelay($retries)
+ {
+ return (int) pow(2, $retries - 1);
+ }
+
+ /**
+ * @param RequestInterface $request
+ * @param array $options
+ *
+ * @return PromiseInterface
+ */
+ public function __invoke(RequestInterface $request, array $options)
+ {
+ if (!isset($options['retries'])) {
+ $options['retries'] = 0;
+ }
+
+ $fn = $this->nextHandler;
+ return $fn($request, $options)
+ ->then(
+ $this->onFulfilled($request, $options),
+ $this->onRejected($request, $options)
+ );
+ }
+
+ private function onFulfilled(RequestInterface $req, array $options)
+ {
+ return function ($value) use ($req, $options) {
+ if (!call_user_func(
+ $this->decider,
+ $options['retries'],
+ $req,
+ $value,
+ null
+ )) {
+ return $value;
+ }
+ return $this->doRetry($req, $options);
+ };
+ }
+
+ private function onRejected(RequestInterface $req, array $options)
+ {
+ return function ($reason) use ($req, $options) {
+ if (!call_user_func(
+ $this->decider,
+ $options['retries'],
+ $req,
+ null,
+ $reason
+ )) {
+ return new RejectedPromise($reason);
+ }
+ return $this->doRetry($req, $options);
+ };
+ }
+
+ private function doRetry(RequestInterface $request, array $options)
+ {
+ $options['delay'] = call_user_func($this->delay, ++$options['retries']);
+
+ return $this($request, $options);
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/TransferStats.php b/server/vendor/guzzlehttp/guzzle/src/TransferStats.php
new file mode 100644
index 0000000..15f717e
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/TransferStats.php
@@ -0,0 +1,126 @@
+<?php
+namespace GuzzleHttp;
+
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\UriInterface;
+
+/**
+ * Represents data at the point after it was transferred either successfully
+ * or after a network error.
+ */
+final class TransferStats
+{
+ private $request;
+ private $response;
+ private $transferTime;
+ private $handlerStats;
+ private $handlerErrorData;
+
+ /**
+ * @param RequestInterface $request Request that was sent.
+ * @param ResponseInterface $response Response received (if any)
+ * @param null $transferTime Total handler transfer time.
+ * @param mixed $handlerErrorData Handler error data.
+ * @param array $handlerStats Handler specific stats.
+ */
+ public function __construct(
+ RequestInterface $request,
+ ResponseInterface $response = null,
+ $transferTime = null,
+ $handlerErrorData = null,
+ $handlerStats = []
+ ) {
+ $this->request = $request;
+ $this->response = $response;
+ $this->transferTime = $transferTime;
+ $this->handlerErrorData = $handlerErrorData;
+ $this->handlerStats = $handlerStats;
+ }
+
+ /**
+ * @return RequestInterface
+ */
+ public function getRequest()
+ {
+ return $this->request;
+ }
+
+ /**
+ * Returns the response that was received (if any).
+ *
+ * @return ResponseInterface|null
+ */
+ public function getResponse()
+ {
+ return $this->response;
+ }
+
+ /**
+ * Returns true if a response was received.
+ *
+ * @return bool
+ */
+ public function hasResponse()
+ {
+ return $this->response !== null;
+ }
+
+ /**
+ * Gets handler specific error data.
+ *
+ * This might be an exception, a integer representing an error code, or
+ * anything else. Relying on this value assumes that you know what handler
+ * you are using.
+ *
+ * @return mixed
+ */
+ public function getHandlerErrorData()
+ {
+ return $this->handlerErrorData;
+ }
+
+ /**
+ * Get the effective URI the request was sent to.
+ *
+ * @return UriInterface
+ */
+ public function getEffectiveUri()
+ {
+ return $this->request->getUri();
+ }
+
+ /**
+ * Get the estimated time the request was being transferred by the handler.
+ *
+ * @return float Time in seconds.
+ */
+ public function getTransferTime()
+ {
+ return $this->transferTime;
+ }
+
+ /**
+ * Gets an array of all of the handler specific transfer data.
+ *
+ * @return array
+ */
+ public function getHandlerStats()
+ {
+ return $this->handlerStats;
+ }
+
+ /**
+ * Get a specific handler statistic from the handler by name.
+ *
+ * @param string $stat Handler specific transfer stat to retrieve.
+ *
+ * @return mixed|null
+ */
+ public function getHandlerStat($stat)
+ {
+ return isset($this->handlerStats[$stat])
+ ? $this->handlerStats[$stat]
+ : null;
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/UriTemplate.php b/server/vendor/guzzlehttp/guzzle/src/UriTemplate.php
new file mode 100644
index 0000000..55dfeb5
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/UriTemplate.php
@@ -0,0 +1,241 @@
+<?php
+namespace GuzzleHttp;
+
+/**
+ * Expands URI templates. Userland implementation of PECL uri_template.
+ *
+ * @link http://tools.ietf.org/html/rfc6570
+ */
+class UriTemplate
+{
+ /** @var string URI template */
+ private $template;
+
+ /** @var array Variables to use in the template expansion */
+ private $variables;
+
+ /** @var array Hash for quick operator lookups */
+ private static $operatorHash = array(
+ '' => array('prefix' => '', 'joiner' => ',', 'query' => false),
+ '+' => array('prefix' => '', 'joiner' => ',', 'query' => false),
+ '#' => array('prefix' => '#', 'joiner' => ',', 'query' => false),
+ '.' => array('prefix' => '.', 'joiner' => '.', 'query' => false),
+ '/' => array('prefix' => '/', 'joiner' => '/', 'query' => false),
+ ';' => array('prefix' => ';', 'joiner' => ';', 'query' => true),
+ '?' => array('prefix' => '?', 'joiner' => '&', 'query' => true),
+ '&' => array('prefix' => '&', 'joiner' => '&', 'query' => true)
+ );
+
+ /** @var array Delimiters */
+ private static $delims = array(':', '/', '?', '#', '[', ']', '@', '!', '$',
+ '&', '\'', '(', ')', '*', '+', ',', ';', '=');
+
+ /** @var array Percent encoded delimiters */
+ private static $delimsPct = array('%3A', '%2F', '%3F', '%23', '%5B', '%5D',
+ '%40', '%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C',
+ '%3B', '%3D');
+
+ public function expand($template, array $variables)
+ {
+ if (false === strpos($template, '{')) {
+ return $template;
+ }
+
+ $this->template = $template;
+ $this->variables = $variables;
+
+ return preg_replace_callback(
+ '/\{([^\}]+)\}/',
+ [$this, 'expandMatch'],
+ $this->template
+ );
+ }
+
+ /**
+ * Parse an expression into parts
+ *
+ * @param string $expression Expression to parse
+ *
+ * @return array Returns an associative array of parts
+ */
+ private function parseExpression($expression)
+ {
+ $result = array();
+
+ if (isset(self::$operatorHash[$expression[0]])) {
+ $result['operator'] = $expression[0];
+ $expression = substr($expression, 1);
+ } else {
+ $result['operator'] = '';
+ }
+
+ foreach (explode(',', $expression) as $value) {
+ $value = trim($value);
+ $varspec = array();
+ if ($colonPos = strpos($value, ':')) {
+ $varspec['value'] = substr($value, 0, $colonPos);
+ $varspec['modifier'] = ':';
+ $varspec['position'] = (int) substr($value, $colonPos + 1);
+ } elseif (substr($value, -1) == '*') {
+ $varspec['modifier'] = '*';
+ $varspec['value'] = substr($value, 0, -1);
+ } else {
+ $varspec['value'] = (string) $value;
+ $varspec['modifier'] = '';
+ }
+ $result['values'][] = $varspec;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Process an expansion
+ *
+ * @param array $matches Matches met in the preg_replace_callback
+ *
+ * @return string Returns the replacement string
+ */
+ private function expandMatch(array $matches)
+ {
+ static $rfc1738to3986 = array('+' => '%20', '%7e' => '~');
+
+ $replacements = array();
+ $parsed = self::parseExpression($matches[1]);
+ $prefix = self::$operatorHash[$parsed['operator']]['prefix'];
+ $joiner = self::$operatorHash[$parsed['operator']]['joiner'];
+ $useQuery = self::$operatorHash[$parsed['operator']]['query'];
+
+ foreach ($parsed['values'] as $value) {
+
+ if (!isset($this->variables[$value['value']])) {
+ continue;
+ }
+
+ $variable = $this->variables[$value['value']];
+ $actuallyUseQuery = $useQuery;
+ $expanded = '';
+
+ if (is_array($variable)) {
+
+ $isAssoc = $this->isAssoc($variable);
+ $kvp = array();
+ foreach ($variable as $key => $var) {
+
+ if ($isAssoc) {
+ $key = rawurlencode($key);
+ $isNestedArray = is_array($var);
+ } else {
+ $isNestedArray = false;
+ }
+
+ if (!$isNestedArray) {
+ $var = rawurlencode($var);
+ if ($parsed['operator'] == '+' ||
+ $parsed['operator'] == '#'
+ ) {
+ $var = $this->decodeReserved($var);
+ }
+ }
+
+ if ($value['modifier'] == '*') {
+ if ($isAssoc) {
+ if ($isNestedArray) {
+ // Nested arrays must allow for deeply nested
+ // structures.
+ $var = strtr(
+ http_build_query([$key => $var]),
+ $rfc1738to3986
+ );
+ } else {
+ $var = $key . '=' . $var;
+ }
+ } elseif ($key > 0 && $actuallyUseQuery) {
+ $var = $value['value'] . '=' . $var;
+ }
+ }
+
+ $kvp[$key] = $var;
+ }
+
+ if (empty($variable)) {
+ $actuallyUseQuery = false;
+ } elseif ($value['modifier'] == '*') {
+ $expanded = implode($joiner, $kvp);
+ if ($isAssoc) {
+ // Don't prepend the value name when using the explode
+ // modifier with an associative array.
+ $actuallyUseQuery = false;
+ }
+ } else {
+ if ($isAssoc) {
+ // When an associative array is encountered and the
+ // explode modifier is not set, then the result must be
+ // a comma separated list of keys followed by their
+ // respective values.
+ foreach ($kvp as $k => &$v) {
+ $v = $k . ',' . $v;
+ }
+ }
+ $expanded = implode(',', $kvp);
+ }
+
+ } else {
+ if ($value['modifier'] == ':') {
+ $variable = substr($variable, 0, $value['position']);
+ }
+ $expanded = rawurlencode($variable);
+ if ($parsed['operator'] == '+' || $parsed['operator'] == '#') {
+ $expanded = $this->decodeReserved($expanded);
+ }
+ }
+
+ if ($actuallyUseQuery) {
+ if (!$expanded && $joiner != '&') {
+ $expanded = $value['value'];
+ } else {
+ $expanded = $value['value'] . '=' . $expanded;
+ }
+ }
+
+ $replacements[] = $expanded;
+ }
+
+ $ret = implode($joiner, $replacements);
+ if ($ret && $prefix) {
+ return $prefix . $ret;
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Determines if an array is associative.
+ *
+ * This makes the assumption that input arrays are sequences or hashes.
+ * This assumption is a tradeoff for accuracy in favor of speed, but it
+ * should work in almost every case where input is supplied for a URI
+ * template.
+ *
+ * @param array $array Array to check
+ *
+ * @return bool
+ */
+ private function isAssoc(array $array)
+ {
+ return $array && array_keys($array)[0] !== 0;
+ }
+
+ /**
+ * Removes percent encoding on reserved characters (used with + and #
+ * modifiers).
+ *
+ * @param string $string String to fix
+ *
+ * @return string
+ */
+ private function decodeReserved($string)
+ {
+ return str_replace(self::$delimsPct, self::$delims, $string);
+ }
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/functions.php b/server/vendor/guzzlehttp/guzzle/src/functions.php
new file mode 100644
index 0000000..5e93b22
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/functions.php
@@ -0,0 +1,284 @@
+<?php
+namespace GuzzleHttp;
+
+use GuzzleHttp\Handler\CurlHandler;
+use GuzzleHttp\Handler\CurlMultiHandler;
+use GuzzleHttp\Handler\Proxy;
+use GuzzleHttp\Handler\StreamHandler;
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Expands a URI template
+ *
+ * @param string $template URI template
+ * @param array $variables Template variables
+ *
+ * @return string
+ */
+function uri_template($template, array $variables)
+{
+ if (extension_loaded('uri_template')) {
+ // @codeCoverageIgnoreStart
+ return \uri_template($template, $variables);
+ // @codeCoverageIgnoreEnd
+ }
+
+ static $uriTemplate;
+ if (!$uriTemplate) {
+ $uriTemplate = new UriTemplate();
+ }
+
+ return $uriTemplate->expand($template, $variables);
+}
+
+/**
+ * Debug function used to describe the provided value type and class.
+ *
+ * @param mixed $input
+ *
+ * @return string Returns a string containing the type of the variable and
+ * if a class is provided, the class name.
+ */
+function describe_type($input)
+{
+ switch (gettype($input)) {
+ case 'object':
+ return 'object(' . get_class($input) . ')';
+ case 'array':
+ return 'array(' . count($input) . ')';
+ default:
+ ob_start();
+ var_dump($input);
+ // normalize float vs double
+ return str_replace('double(', 'float(', rtrim(ob_get_clean()));
+ }
+}
+
+/**
+ * Parses an array of header lines into an associative array of headers.
+ *
+ * @param array $lines Header lines array of strings in the following
+ * format: "Name: Value"
+ * @return array
+ */
+function headers_from_lines($lines)
+{
+ $headers = [];
+
+ foreach ($lines as $line) {
+ $parts = explode(':', $line, 2);
+ $headers[trim($parts[0])][] = isset($parts[1])
+ ? trim($parts[1])
+ : null;
+ }
+
+ return $headers;
+}
+
+/**
+ * Returns a debug stream based on the provided variable.
+ *
+ * @param mixed $value Optional value
+ *
+ * @return resource
+ */
+function debug_resource($value = null)
+{
+ if (is_resource($value)) {
+ return $value;
+ } elseif (defined('STDOUT')) {
+ return STDOUT;
+ }
+
+ return fopen('php://output', 'w');
+}
+
+/**
+ * Chooses and creates a default handler to use based on the environment.
+ *
+ * The returned handler is not wrapped by any default middlewares.
+ *
+ * @throws \RuntimeException if no viable Handler is available.
+ * @return callable Returns the best handler for the given system.
+ */
+function choose_handler()
+{
+ $handler = null;
+ if (function_exists('curl_multi_exec') && function_exists('curl_exec')) {
+ $handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler());
+ } elseif (function_exists('curl_exec')) {
+ $handler = new CurlHandler();
+ } elseif (function_exists('curl_multi_exec')) {
+ $handler = new CurlMultiHandler();
+ }
+
+ if (ini_get('allow_url_fopen')) {
+ $handler = $handler
+ ? Proxy::wrapStreaming($handler, new StreamHandler())
+ : new StreamHandler();
+ } elseif (!$handler) {
+ throw new \RuntimeException('GuzzleHttp requires cURL, the '
+ . 'allow_url_fopen ini setting, or a custom HTTP handler.');
+ }
+
+ return $handler;
+}
+
+/**
+ * Get the default User-Agent string to use with Guzzle
+ *
+ * @return string
+ */
+function default_user_agent()
+{
+ static $defaultAgent = '';
+
+ if (!$defaultAgent) {
+ $defaultAgent = 'GuzzleHttp/' . Client::VERSION;
+ if (extension_loaded('curl') && function_exists('curl_version')) {
+ $defaultAgent .= ' curl/' . \curl_version()['version'];
+ }
+ $defaultAgent .= ' PHP/' . PHP_VERSION;
+ }
+
+ return $defaultAgent;
+}
+
+/**
+ * Returns the default cacert bundle for the current system.
+ *
+ * First, the openssl.cafile and curl.cainfo php.ini settings are checked.
+ * If those settings are not configured, then the common locations for
+ * bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X
+ * and Windows are checked. If any of these file locations are found on
+ * disk, they will be utilized.
+ *
+ * Note: the result of this function is cached for subsequent calls.
+ *
+ * @return string
+ * @throws \RuntimeException if no bundle can be found.
+ */
+function default_ca_bundle()
+{
+ static $cached = null;
+ static $cafiles = [
+ // Red Hat, CentOS, Fedora (provided by the ca-certificates package)
+ '/etc/pki/tls/certs/ca-bundle.crt',
+ // Ubuntu, Debian (provided by the ca-certificates package)
+ '/etc/ssl/certs/ca-certificates.crt',
+ // FreeBSD (provided by the ca_root_nss package)
+ '/usr/local/share/certs/ca-root-nss.crt',
+ // OS X provided by homebrew (using the default path)
+ '/usr/local/etc/openssl/cert.pem',
+ // Google app engine
+ '/etc/ca-certificates.crt',
+ // Windows?
+ 'C:\\windows\\system32\\curl-ca-bundle.crt',
+ 'C:\\windows\\curl-ca-bundle.crt',
+ ];
+
+ if ($cached) {
+ return $cached;
+ }
+
+ if ($ca = ini_get('openssl.cafile')) {
+ return $cached = $ca;
+ }
+
+ if ($ca = ini_get('curl.cainfo')) {
+ return $cached = $ca;
+ }
+
+ foreach ($cafiles as $filename) {
+ if (file_exists($filename)) {
+ return $cached = $filename;
+ }
+ }
+
+ throw new \RuntimeException(<<< EOT
+No system CA bundle could be found in any of the the common system locations.
+PHP versions earlier than 5.6 are not properly configured to use the system's
+CA bundle by default. In order to verify peer certificates, you will need to
+supply the path on disk to a certificate bundle to the 'verify' request
+option: http://docs.guzzlephp.org/en/latest/clients.html#verify. If you do not
+need a specific certificate bundle, then Mozilla provides a commonly used CA
+bundle which can be downloaded here (provided by the maintainer of cURL):
+https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt. Once
+you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP
+ini setting to point to the path to the file, allowing you to omit the 'verify'
+request option. See http://curl.haxx.se/docs/sslcerts.html for more
+information.
+EOT
+ );
+}
+
+/**
+ * Creates an associative array of lowercase header names to the actual
+ * header casing.
+ *
+ * @param array $headers
+ *
+ * @return array
+ */
+function normalize_header_keys(array $headers)
+{
+ $result = [];
+ foreach (array_keys($headers) as $key) {
+ $result[strtolower($key)] = $key;
+ }
+
+ return $result;
+}
+
+/**
+ * Returns true if the provided host matches any of the no proxy areas.
+ *
+ * This method will strip a port from the host if it is present. Each pattern
+ * can be matched with an exact match (e.g., "foo.com" == "foo.com") or a
+ * partial match: (e.g., "foo.com" == "baz.foo.com" and ".foo.com" ==
+ * "baz.foo.com", but ".foo.com" != "foo.com").
+ *
+ * Areas are matched in the following cases:
+ * 1. "*" (without quotes) always matches any hosts.
+ * 2. An exact match.
+ * 3. The area starts with "." and the area is the last part of the host. e.g.
+ * '.mit.edu' will match any host that ends with '.mit.edu'.
+ *
+ * @param string $host Host to check against the patterns.
+ * @param array $noProxyArray An array of host patterns.
+ *
+ * @return bool
+ */
+function is_host_in_noproxy($host, array $noProxyArray)
+{
+ if (strlen($host) === 0) {
+ throw new \InvalidArgumentException('Empty host provided');
+ }
+
+ // Strip port if present.
+ if (strpos($host, ':')) {
+ $host = explode($host, ':', 2)[0];
+ }
+
+ foreach ($noProxyArray as $area) {
+ // Always match on wildcards.
+ if ($area === '*') {
+ return true;
+ } elseif (empty($area)) {
+ // Don't match on empty values.
+ continue;
+ } elseif ($area === $host) {
+ // Exact matches.
+ return true;
+ } else {
+ // Special match if the area when prefixed with ".". Remove any
+ // existing leading "." and add a new leading ".".
+ $area = '.' . ltrim($area, '.');
+ if (substr($host, -(strlen($area))) === $area) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
diff --git a/server/vendor/guzzlehttp/guzzle/src/functions_include.php b/server/vendor/guzzlehttp/guzzle/src/functions_include.php
new file mode 100644
index 0000000..a93393a
--- /dev/null
+++ b/server/vendor/guzzlehttp/guzzle/src/functions_include.php
@@ -0,0 +1,6 @@
+<?php
+
+// Don't redefine the functions if included multiple times.
+if (!function_exists('GuzzleHttp\uri_template')) {
+ require __DIR__ . '/functions.php';
+}
diff --git a/server/vendor/guzzlehttp/promises/.gitignore b/server/vendor/guzzlehttp/promises/.gitignore
new file mode 100644
index 0000000..83ec41e
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/.gitignore
@@ -0,0 +1,11 @@
+phpunit.xml
+composer.phar
+composer.lock
+composer-test.lock
+vendor/
+build/artifacts/
+artifacts/
+docs/_build
+docs/*.pyc
+.idea
+.DS_STORE
diff --git a/server/vendor/guzzlehttp/promises/.travis.yml b/server/vendor/guzzlehttp/promises/.travis.yml
new file mode 100644
index 0000000..4f4d2b8
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/.travis.yml
@@ -0,0 +1,19 @@
+language: php
+
+php:
+ - 5.5
+ - 5.6
+ - 7.0
+ - hhvm
+
+sudo: false
+
+install:
+ - travis_retry composer install --no-interaction --prefer-source
+
+script: make test
+
+matrix:
+ allow_failures:
+ - php: hhvm
+ fast_finish: true
diff --git a/server/vendor/guzzlehttp/promises/CHANGELOG.md b/server/vendor/guzzlehttp/promises/CHANGELOG.md
new file mode 100644
index 0000000..4031cb8
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/CHANGELOG.md
@@ -0,0 +1,21 @@
+# CHANGELOG
+
+## 1.0.3 - 2015-10-15
+
+* Update EachPromise to immediately resolve when the underlying promise iterator
+ is empty. Previously, such a promise would throw an exception when its `wait`
+ function was called.
+
+## 1.0.2 - 2015-05-15
+
+* Conditionally require functions.php.
+
+## 1.0.1 - 2015-06-24
+
+* Updating EachPromise to call next on the underlying promise iterator as late
+ as possible to ensure that generators that generate new requests based on
+ callbacks are not iterated until after callbacks are invoked.
+
+## 1.0.0 - 2015-05-12
+
+* Initial release
diff --git a/server/vendor/guzzlehttp/promises/LICENSE b/server/vendor/guzzlehttp/promises/LICENSE
new file mode 100644
index 0000000..581d95f
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/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/server/vendor/guzzlehttp/promises/Makefile b/server/vendor/guzzlehttp/promises/Makefile
new file mode 100644
index 0000000..8d5b3ef
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/Makefile
@@ -0,0 +1,13 @@
+all: clean test
+
+test:
+ vendor/bin/phpunit
+
+coverage:
+ vendor/bin/phpunit --coverage-html=artifacts/coverage
+
+view-coverage:
+ open artifacts/coverage/index.html
+
+clean:
+ rm -rf artifacts/*
diff --git a/server/vendor/guzzlehttp/promises/README.md b/server/vendor/guzzlehttp/promises/README.md
new file mode 100644
index 0000000..c6780ab
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/README.md
@@ -0,0 +1,501 @@
+# Guzzle Promises
+
+[Promises/A+](https://promisesaplus.com/) implementation that handles promise
+chaining and resolution iteratively, allowing for "infinite" promise chaining
+while keeping the stack size constant. Read [this blog post](https://blog.domenic.me/youre-missing-the-point-of-promises/)
+for a general introduction to promises.
+
+- [Features](#features)
+- [Quick start](#quick-start)
+- [Synchronous wait](#synchronous-wait)
+- [Cancellation](#cancellation)
+- [API](#api)
+ - [Promise](#promise)
+ - [FulfilledPromise](#fulfilledpromise)
+ - [RejectedPromise](#rejectedpromise)
+- [Promise interop](#promise-interop)
+- [Implementation notes](#implementation-notes)
+
+
+# Features
+
+- [Promises/A+](https://promisesaplus.com/) implementation.
+- Promise resolution and chaining is handled iteratively, allowing for
+ "infinite" promise chaining.
+- Promises have a synchronous `wait` method.
+- Promises can be cancelled.
+- Works with any object that has a `then` function.
+- C# style async/await coroutine promises using
+ `GuzzleHttp\Promise\coroutine()`.
+
+
+# Quick start
+
+A *promise* represents the eventual result of an asynchronous operation. The
+primary way of interacting with a promise is through its `then` method, which
+registers callbacks to receive either a promise's eventual value or the reason
+why the promise cannot be fulfilled.
+
+
+## Callbacks
+
+Callbacks are registered with the `then` method by providing an optional
+`$onFulfilled` followed by an optional `$onRejected` function.
+
+
+```php
+use GuzzleHttp\Promise\Promise;
+
+$promise = new Promise();
+$promise->then(
+ // $onFulfilled
+ function ($value) {
+ echo 'The promise was fulfilled.';
+ },
+ // $onRejected
+ function ($reason) {
+ echo 'The promise was rejected.';
+ }
+);
+```
+
+*Resolving* a promise means that you either fulfill a promise with a *value* or
+reject a promise with a *reason*. Resolving a promises triggers callbacks
+registered with the promises's `then` method. These callbacks are triggered
+only once and in the order in which they were added.
+
+
+## Resolving a promise
+
+Promises are fulfilled using the `resolve($value)` method. Resolving a promise
+with any value other than a `GuzzleHttp\Promise\RejectedPromise` will trigger
+all of the onFulfilled callbacks (resolving a promise with a rejected promise
+will reject the promise and trigger the `$onRejected` callbacks).
+
+```php
+use GuzzleHttp\Promise\Promise;
+
+$promise = new Promise();
+$promise
+ ->then(function ($value) {
+ // Return a value and don't break the chain
+ return "Hello, " . $value;
+ })
+ // This then is executed after the first then and receives the value
+ // returned from the first then.
+ ->then(function ($value) {
+ echo $value;
+ });
+
+// Resolving the promise triggers the $onFulfilled callbacks and outputs
+// "Hello, reader".
+$promise->resolve('reader.');
+```
+
+
+## Promise forwarding
+
+Promises can be chained one after the other. Each then in the chain is a new
+promise. The return value of of a promise is what's forwarded to the next
+promise in the chain. Returning a promise in a `then` callback will cause the
+subsequent promises in the chain to only be fulfilled when the returned promise
+has been fulfilled. The next promise in the chain will be invoked with the
+resolved value of the promise.
+
+```php
+use GuzzleHttp\Promise\Promise;
+
+$promise = new Promise();
+$nextPromise = new Promise();
+
+$promise
+ ->then(function ($value) use ($nextPromise) {
+ echo $value;
+ return $nextPromise;
+ })
+ ->then(function ($value) {
+ echo $value;
+ });
+
+// Triggers the first callback and outputs "A"
+$promise->resolve('A');
+// Triggers the second callback and outputs "B"
+$nextPromise->resolve('B');
+```
+
+## Promise rejection
+
+When a promise is rejected, the `$onRejected` callbacks are invoked with the
+rejection reason.
+
+```php
+use GuzzleHttp\Promise\Promise;
+
+$promise = new Promise();
+$promise->then(null, function ($reason) {
+ echo $reason;
+});
+
+$promise->reject('Error!');
+// Outputs "Error!"
+```
+
+## Rejection forwarding
+
+If an exception is thrown in an `$onRejected` callback, subsequent
+`$onRejected` callbacks are invoked with the thrown exception as the reason.
+
+```php
+use GuzzleHttp\Promise\Promise;
+
+$promise = new Promise();
+$promise->then(null, function ($reason) {
+ throw new \Exception($reason);
+})->then(null, function ($reason) {
+ assert($reason->getMessage() === 'Error!');
+});
+
+$promise->reject('Error!');
+```
+
+You can also forward a rejection down the promise chain by returning a
+`GuzzleHttp\Promise\RejectedPromise` in either an `$onFulfilled` or
+`$onRejected` callback.
+
+```php
+use GuzzleHttp\Promise\Promise;
+use GuzzleHttp\Promise\RejectedPromise;
+
+$promise = new Promise();
+$promise->then(null, function ($reason) {
+ return new RejectedPromise($reason);
+})->then(null, function ($reason) {
+ assert($reason === 'Error!');
+});
+
+$promise->reject('Error!');
+```
+
+If an exception is not thrown in a `$onRejected` callback and the callback
+does not return a rejected promise, downstream `$onFulfilled` callbacks are
+invoked using the value returned from the `$onRejected` callback.
+
+```php
+use GuzzleHttp\Promise\Promise;
+use GuzzleHttp\Promise\RejectedPromise;
+
+$promise = new Promise();
+$promise
+ ->then(null, function ($reason) {
+ return "It's ok";
+ })
+ ->then(function ($value) {
+ assert($value === "It's ok");
+ });
+
+$promise->reject('Error!');
+```
+
+# Synchronous wait
+
+You can synchronously force promises to complete using a promise's `wait`
+method. When creating a promise, you can provide a wait function that is used
+to synchronously force a promise to complete. When a wait function is invoked
+it is expected to deliver a value to the promise or reject the promise. If the
+wait function does not deliver a value, then an exception is thrown. The wait
+function provided to a promise constructor is invoked when the `wait` function
+of the promise is called.
+
+```php
+$promise = new Promise(function () use (&$promise) {
+ $promise->deliver('foo');
+});
+
+// Calling wait will return the value of the promise.
+echo $promise->wait(); // outputs "foo"
+```
+
+If an exception is encountered while invoking the wait function of a promise,
+the promise is rejected with the exception and the exception is thrown.
+
+```php
+$promise = new Promise(function () use (&$promise) {
+ throw new \Exception('foo');
+});
+
+$promise->wait(); // throws the exception.
+```
+
+Calling `wait` on a promise that has been fulfilled will not trigger the wait
+function. It will simply return the previously delivered value.
+
+```php
+$promise = new Promise(function () { die('this is not called!'); });
+$promise->deliver('foo');
+echo $promise->wait(); // outputs "foo"
+```
+
+Calling `wait` on a promise that has been rejected will throw an exception. If
+the rejection reason is an instance of `\Exception` the reason is thrown.
+Otherwise, a `GuzzleHttp\Promise\RejectionException` is thrown and the reason
+can be obtained by calling the `getReason` method of the exception.
+
+```php
+$promise = new Promise();
+$promise->reject('foo');
+$promise->wait();
+```
+
+> PHP Fatal error: Uncaught exception 'GuzzleHttp\Promise\RejectionException' with message 'The promise was rejected with value: foo'
+
+
+## Unwrapping a promise
+
+When synchronously waiting on a promise, you are joining the state of the
+promise into the current state of execution (i.e., return the value of the
+promise if it was fulfilled or throw an exception if it was rejected). This is
+called "unwrapping" the promise. Waiting on a promise will by default unwrap
+the promise state.
+
+You can force a promise to resolve and *not* unwrap the state of the promise
+by passing `false` to the first argument of the `wait` function:
+
+```php
+$promise = new Promise();
+$promise->reject('foo');
+// This will not throw an exception. It simply ensures the promise has
+// been resolved.
+$promise->wait(false);
+```
+
+When unwrapping a promise, the delivered value of the promise will be waited
+upon until the unwrapped value is not a promise. This means that if you resolve
+promise A with a promise B and unwrap promise A, the value returned by the
+wait function will be the value delivered to promise B.
+
+**Note**: when you do not unwrap the promise, no value is returned.
+
+
+# Cancellation
+
+You can cancel a promise that has not yet been fulfilled using the `cancel()`
+method of a promise. When creating a promise you can provide an optional
+cancel function that when invoked cancels the action of computing a resolution
+of the promise.
+
+
+# API
+
+
+## Promise
+
+When creating a promise object, you can provide an optional `$waitFn` and
+`$cancelFn`. `$waitFn` is a function that is invoked with no arguments and is
+expected to resolve the promise. `$cancelFn` is a function with no arguments
+that is expected to cancel the computation of a promise. It is invoked when the
+`cancel()` method of a promise is called.
+
+```php
+use GuzzleHttp\Promise\Promise;
+
+$promise = new Promise(
+ function () use (&$promise) {
+ $promise->resolve('waited');
+ },
+ function () {
+ // do something that will cancel the promise computation (e.g., close
+ // a socket, cancel a database query, etc...)
+ }
+);
+
+assert('waited' === $promise->wait());
+```
+
+A promise has the following methods:
+
+- `then(callable $onFulfilled, callable $onRejected) : PromiseInterface`
+
+ Creates a new promise that is fulfilled or rejected when the promise is
+ resolved.
+
+- `wait($unwrap = true) : mixed`
+
+ Synchronously waits on the promise to complete.
+
+ `$unwrap` controls whether or not the value of the promise is returned for a
+ fulfilled promise or if an exception is thrown if the promise is rejected.
+ This is set to `true` by default.
+
+- `cancel()`
+
+ Attempts to cancel the promise if possible. The promise being cancelled and
+ the parent most ancestor that has not yet been resolved will also be
+ cancelled. Any promises waiting on the cancelled promise to resolve will also
+ be cancelled.
+
+- `getState() : string`
+
+ Returns the state of the promise. One of `pending`, `fulfilled`, or
+ `rejected`.
+
+- `resolve($value)`
+
+ Fulfills the promise with the given `$value`.
+
+- `reject($reason)`
+
+ Rejects the promise with the given `$reason`.
+
+
+## FulfilledPromise
+
+A fulfilled promise can be created to represent a promise that has been
+fulfilled.
+
+```php
+use GuzzleHttp\Promise\FulfilledPromise;
+
+$promise = new FulfilledPromise('value');
+
+// Fulfilled callbacks are immediately invoked.
+$promise->then(function ($value) {
+ echo $value;
+});
+```
+
+
+## RejectedPromise
+
+A rejected promise can be created to represent a promise that has been
+rejected.
+
+```php
+use GuzzleHttp\Promise\RejectedPromise;
+
+$promise = new RejectedPromise('Error');
+
+// Rejected callbacks are immediately invoked.
+$promise->then(null, function ($reason) {
+ echo $reason;
+});
+```
+
+
+# Promise interop
+
+This library works with foreign promises that have a `then` method. This means
+you can use Guzzle promises with [React promises](https://github.com/reactphp/promise)
+for example. When a foreign promise is returned inside of a then method
+callback, promise resolution will occur recursively.
+
+```php
+// Create a React promise
+$deferred = new React\Promise\Deferred();
+$reactPromise = $deferred->promise();
+
+// Create a Guzzle promise that is fulfilled with a React promise.
+$guzzlePromise = new \GuzzleHttp\Promise\Promise();
+$guzzlePromise->then(function ($value) use ($reactPromise) {
+ // Do something something with the value...
+ // Return the React promise
+ return $reactPromise;
+});
+```
+
+Please note that wait and cancel chaining is no longer possible when forwarding
+a foreign promise. You will need to wrap a third-party promise with a Guzzle
+promise in order to utilize wait and cancel functions with foreign promises.
+
+
+## Event Loop Integration
+
+In order to keep the stack size constant, Guzzle promises are resolved
+asynchronously using a task queue. When waiting on promises synchronously, the
+task queue will be automatically run to ensure that the blocking promise and
+any forwarded promises are resolved. When using promises asynchronously in an
+event loop, you will need to run the task queue on each tick of the loop. If
+you do not run the task queue, then promises will not be resolved.
+
+You can run the task queue using the `run()` method of the global task queue
+instance.
+
+```php
+// Get the global task queue
+$queue = \GuzzleHttp\Promise\queue();
+$queue->run();
+```
+
+For example, you could use Guzzle promises with React using a periodic timer:
+
+```php
+$loop = React\EventLoop\Factory::create();
+$loop->addPeriodicTimer(0, [$queue, 'run']);
+```
+
+*TODO*: Perhaps adding a `futureTick()` on each tick would be faster?
+
+
+# Implementation notes
+
+
+## Promise resolution and chaining is handled iteratively
+
+By shuffling pending handlers from one owner to another, promises are
+resolved iteratively, allowing for "infinite" then chaining.
+
+```php
+<?php
+require 'vendor/autoload.php';
+
+use GuzzleHttp\Promise\Promise;
+
+$parent = new Promise();
+$p = $parent;
+
+for ($i = 0; $i < 1000; $i++) {
+ $p = $p->then(function ($v) {
+ // The stack size remains constant (a good thing)
+ echo xdebug_get_stack_depth() . ', ';
+ return $v + 1;
+ });
+}
+
+$parent->resolve(0);
+var_dump($p->wait()); // int(1000)
+
+```
+
+When a promise is fulfilled or rejected with a non-promise value, the promise
+then takes ownership of the handlers of each child promise and delivers values
+down the chain without using recursion.
+
+When a promise is resolved with another promise, the original promise transfers
+all of its pending handlers to the new promise. When the new promise is
+eventually resolved, all of the pending handlers are delivered the forwarded
+value.
+
+
+## A promise is the deferred.
+
+Some promise libraries implement promises using a deferred object to represent
+a computation and a promise object to represent the delivery of the result of
+the computation. This is a nice separation of computation and delivery because
+consumers of the promise cannot modify the value that will be eventually
+delivered.
+
+One side effect of being able to implement promise resolution and chaining
+iteratively is that you need to be able for one promise to reach into the state
+of another promise to shuffle around ownership of handlers. In order to achieve
+this without making the handlers of a promise publicly mutable, a promise is
+also the deferred value, allowing promises of the same parent class to reach
+into and modify the private properties of promises of the same type. While this
+does allow consumers of the value to modify the resolution or rejection of the
+deferred, it is a small price to pay for keeping the stack size constant.
+
+```php
+$promise = new Promise();
+$promise->then(function ($value) { echo $value; });
+// The promise is the deferred value, so you can deliver a value to it.
+$promise->deliver('foo');
+// prints "foo"
+```
diff --git a/server/vendor/guzzlehttp/promises/composer.json b/server/vendor/guzzlehttp/promises/composer.json
new file mode 100644
index 0000000..f13844b
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/composer.json
@@ -0,0 +1,31 @@
+{
+ "name": "guzzlehttp/promises",
+ "type": "library",
+ "description": "Guzzle promises library",
+ "keywords": ["promise"],
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "require": {
+ "php": ">=5.5.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Promise\\": "src/"
+ },
+ "files": ["src/functions_include.php"]
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ }
+}
diff --git a/server/vendor/guzzlehttp/promises/phpunit.xml.dist b/server/vendor/guzzlehttp/promises/phpunit.xml.dist
new file mode 100644
index 0000000..500cd53
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/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/server/vendor/guzzlehttp/promises/src/AggregateException.php b/server/vendor/guzzlehttp/promises/src/AggregateException.php
new file mode 100644
index 0000000..6a5690c
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/src/AggregateException.php
@@ -0,0 +1,16 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * Exception thrown when too many errors occur in the some() or any() methods.
+ */
+class AggregateException extends RejectionException
+{
+ public function __construct($msg, array $reasons)
+ {
+ parent::__construct(
+ $reasons,
+ sprintf('%s; %d rejected promises', $msg, count($reasons))
+ );
+ }
+}
diff --git a/server/vendor/guzzlehttp/promises/src/CancellationException.php b/server/vendor/guzzlehttp/promises/src/CancellationException.php
new file mode 100644
index 0000000..cb360b8
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/src/CancellationException.php
@@ -0,0 +1,9 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * Exception that is set as the reason for a promise that has been cancelled.
+ */
+class CancellationException extends RejectionException
+{
+}
diff --git a/server/vendor/guzzlehttp/promises/src/EachPromise.php b/server/vendor/guzzlehttp/promises/src/EachPromise.php
new file mode 100644
index 0000000..5918429
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/src/EachPromise.php
@@ -0,0 +1,207 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * Represents a promise that iterates over many promises and invokes
+ * side-effect functions in the process.
+ */
+class EachPromise implements PromisorInterface
+{
+ private $pending = [];
+
+ /** @var \Iterator */
+ private $iterable;
+
+ /** @var callable|int */
+ private $concurrency;
+
+ /** @var callable */
+ private $onFulfilled;
+
+ /** @var callable */
+ private $onRejected;
+
+ /** @var Promise */
+ private $aggregate;
+
+ /**
+ * Configuration hash can include the following key value pairs:
+ *
+ * - fulfilled: (callable) Invoked when a promise fulfills. The function
+ * is invoked with three arguments: the fulfillment value, the index
+ * position from the iterable list of the promise, and the aggregate
+ * promise that manages all of the promises. The aggregate promise may
+ * be resolved from within the callback to short-circuit the promise.
+ * - rejected: (callable) Invoked when a promise is rejected. The
+ * function is invoked with three arguments: the rejection reason, the
+ * index position from the iterable list of the promise, and the
+ * aggregate promise that manages all of the promises. The aggregate
+ * promise may be resolved from within the callback to short-circuit
+ * the promise.
+ * - concurrency: (integer) Pass this configuration option to limit the
+ * allowed number of outstanding concurrently executing promises,
+ * creating a capped pool of promises. There is no limit by default.
+ *
+ * @param mixed $iterable Promises or values to iterate.
+ * @param array $config Configuration options
+ */
+ public function __construct($iterable, array $config = [])
+ {
+ $this->iterable = iter_for($iterable);
+
+ if (isset($config['concurrency'])) {
+ $this->concurrency = $config['concurrency'];
+ }
+
+ if (isset($config['fulfilled'])) {
+ $this->onFulfilled = $config['fulfilled'];
+ }
+
+ if (isset($config['rejected'])) {
+ $this->onRejected = $config['rejected'];
+ }
+ }
+
+ public function promise()
+ {
+ if ($this->aggregate) {
+ return $this->aggregate;
+ }
+
+ try {
+ $this->createPromise();
+ $this->iterable->rewind();
+ $this->refillPending();
+ } catch (\Exception $e) {
+ $this->aggregate->reject($e);
+ }
+
+ return $this->aggregate;
+ }
+
+ private function createPromise()
+ {
+ $this->aggregate = new Promise(function () {
+ reset($this->pending);
+ if (empty($this->pending) && !$this->iterable->valid()) {
+ $this->aggregate->resolve(null);
+ return;
+ }
+
+ // Consume a potentially fluctuating list of promises while
+ // ensuring that indexes are maintained (precluding array_shift).
+ while ($promise = current($this->pending)) {
+ next($this->pending);
+ $promise->wait();
+ if ($this->aggregate->getState() !== PromiseInterface::PENDING) {
+ return;
+ }
+ }
+ });
+
+ // Clear the references when the promise is resolved.
+ $clearFn = function () {
+ $this->iterable = $this->concurrency = $this->pending = null;
+ $this->onFulfilled = $this->onRejected = null;
+ };
+
+ $this->aggregate->then($clearFn, $clearFn);
+ }
+
+ private function refillPending()
+ {
+ if (!$this->concurrency) {
+ // Add all pending promises.
+ while ($this->addPending() && $this->advanceIterator());
+ return;
+ }
+
+ // Add only up to N pending promises.
+ $concurrency = is_callable($this->concurrency)
+ ? call_user_func($this->concurrency, count($this->pending))
+ : $this->concurrency;
+ $concurrency = max($concurrency - count($this->pending), 0);
+ // Concurrency may be set to 0 to disallow new promises.
+ if (!$concurrency) {
+ return;
+ }
+ // Add the first pending promise.
+ $this->addPending();
+ // Note this is special handling for concurrency=1 so that we do
+ // not advance the iterator after adding the first promise. This
+ // helps work around issues with generators that might not have the
+ // next value to yield until promise callbacks are called.
+ while (--$concurrency
+ && $this->advanceIterator()
+ && $this->addPending());
+ }
+
+ private function addPending()
+ {
+ if (!$this->iterable || !$this->iterable->valid()) {
+ return false;
+ }
+
+ $promise = promise_for($this->iterable->current());
+ $idx = $this->iterable->key();
+
+ $this->pending[$idx] = $promise->then(
+ function ($value) use ($idx) {
+ if ($this->onFulfilled) {
+ call_user_func(
+ $this->onFulfilled, $value, $idx, $this->aggregate
+ );
+ }
+ $this->step($idx);
+ },
+ function ($reason) use ($idx) {
+ if ($this->onRejected) {
+ call_user_func(
+ $this->onRejected, $reason, $idx, $this->aggregate
+ );
+ }
+ $this->step($idx);
+ }
+ );
+
+ return true;
+ }
+
+ private function advanceIterator()
+ {
+ try {
+ $this->iterable->next();
+ return true;
+ } catch (\Exception $e) {
+ $this->aggregate->reject($e);
+ return false;
+ }
+ }
+
+ private function step($idx)
+ {
+ // If the promise was already resolved, then ignore this step.
+ if ($this->aggregate->getState() !== PromiseInterface::PENDING) {
+ return;
+ }
+
+ unset($this->pending[$idx]);
+ $this->advanceIterator();
+
+ if (!$this->checkIfFinished()) {
+ // Add more pending promises if possible.
+ $this->refillPending();
+ }
+ }
+
+ private function checkIfFinished()
+ {
+ if (!$this->pending && !$this->iterable->valid()) {
+ // Resolve the promise if there's nothing left to do.
+ $this->aggregate->resolve(null);
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/server/vendor/guzzlehttp/promises/src/FulfilledPromise.php b/server/vendor/guzzlehttp/promises/src/FulfilledPromise.php
new file mode 100644
index 0000000..5596296
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/src/FulfilledPromise.php
@@ -0,0 +1,80 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * A promise that has been fulfilled.
+ *
+ * Thenning off of this promise will invoke the onFulfilled callback
+ * immediately and ignore other callbacks.
+ */
+class FulfilledPromise implements PromiseInterface
+{
+ private $value;
+
+ public function __construct($value)
+ {
+ if (method_exists($value, 'then')) {
+ throw new \InvalidArgumentException(
+ 'You cannot create a FulfilledPromise with a promise.');
+ }
+
+ $this->value = $value;
+ }
+
+ public function then(
+ callable $onFulfilled = null,
+ callable $onRejected = null
+ ) {
+ // Return itself if there is no onFulfilled function.
+ if (!$onFulfilled) {
+ return $this;
+ }
+
+ $queue = queue();
+ $p = new Promise([$queue, 'run']);
+ $value = $this->value;
+ $queue->add(static function () use ($p, $value, $onFulfilled) {
+ if ($p->getState() === self::PENDING) {
+ try {
+ $p->resolve($onFulfilled($value));
+ } catch (\Exception $e) {
+ $p->reject($e);
+ }
+ }
+ });
+
+ return $p;
+ }
+
+ public function otherwise(callable $onRejected)
+ {
+ return $this->then(null, $onRejected);
+ }
+
+ public function wait($unwrap = true, $defaultDelivery = null)
+ {
+ return $unwrap ? $this->value : null;
+ }
+
+ public function getState()
+ {
+ return self::FULFILLED;
+ }
+
+ public function resolve($value)
+ {
+ if ($value !== $this->value) {
+ throw new \LogicException("Cannot resolve a fulfilled promise");
+ }
+ }
+
+ public function reject($reason)
+ {
+ throw new \LogicException("Cannot reject a fulfilled promise");
+ }
+
+ public function cancel()
+ {
+ // pass
+ }
+}
diff --git a/server/vendor/guzzlehttp/promises/src/Promise.php b/server/vendor/guzzlehttp/promises/src/Promise.php
new file mode 100644
index 0000000..c2cf969
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/src/Promise.php
@@ -0,0 +1,268 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * Promises/A+ implementation that avoids recursion when possible.
+ *
+ * @link https://promisesaplus.com/
+ */
+class Promise implements PromiseInterface
+{
+ private $state = self::PENDING;
+ private $result;
+ private $cancelFn;
+ private $waitFn;
+ private $waitList;
+ private $handlers = [];
+
+ /**
+ * @param callable $waitFn Fn that when invoked resolves the promise.
+ * @param callable $cancelFn Fn that when invoked cancels the promise.
+ */
+ public function __construct(
+ callable $waitFn = null,
+ callable $cancelFn = null
+ ) {
+ $this->waitFn = $waitFn;
+ $this->cancelFn = $cancelFn;
+ }
+
+ public function then(
+ callable $onFulfilled = null,
+ callable $onRejected = null
+ ) {
+ if ($this->state === self::PENDING) {
+ $p = new Promise(null, [$this, 'cancel']);
+ $this->handlers[] = [$p, $onFulfilled, $onRejected];
+ $p->waitList = $this->waitList;
+ $p->waitList[] = $this;
+ return $p;
+ }
+
+ // Return a fulfilled promise and immediately invoke any callbacks.
+ if ($this->state === self::FULFILLED) {
+ return $onFulfilled
+ ? promise_for($this->result)->then($onFulfilled)
+ : promise_for($this->result);
+ }
+
+ // It's either cancelled or rejected, so return a rejected promise
+ // and immediately invoke any callbacks.
+ $rejection = rejection_for($this->result);
+ return $onRejected ? $rejection->then(null, $onRejected) : $rejection;
+ }
+
+ public function otherwise(callable $onRejected)
+ {
+ return $this->then(null, $onRejected);
+ }
+
+ public function wait($unwrap = true)
+ {
+ $this->waitIfPending();
+
+ if (!$unwrap) {
+ return null;
+ }
+
+ if ($this->result instanceof PromiseInterface) {
+ return $this->result->wait($unwrap);
+ } elseif ($this->state === self::FULFILLED) {
+ return $this->result;
+ } else {
+ // It's rejected so "unwrap" and throw an exception.
+ throw exception_for($this->result);
+ }
+ }
+
+ public function getState()
+ {
+ return $this->state;
+ }
+
+ public function cancel()
+ {
+ if ($this->state !== self::PENDING) {
+ return;
+ }
+
+ $this->waitFn = $this->waitList = null;
+
+ if ($this->cancelFn) {
+ $fn = $this->cancelFn;
+ $this->cancelFn = null;
+ try {
+ $fn();
+ } catch (\Exception $e) {
+ $this->reject($e);
+ }
+ }
+
+ // Reject the promise only if it wasn't rejected in a then callback.
+ if ($this->state === self::PENDING) {
+ $this->reject(new CancellationException('Promise has been cancelled'));
+ }
+ }
+
+ public function resolve($value)
+ {
+ $this->settle(self::FULFILLED, $value);
+ }
+
+ public function reject($reason)
+ {
+ $this->settle(self::REJECTED, $reason);
+ }
+
+ private function settle($state, $value)
+ {
+ if ($this->state !== self::PENDING) {
+ // Ignore calls with the same resolution.
+ if ($state === $this->state && $value === $this->result) {
+ return;
+ }
+ throw $this->state === $state
+ ? new \LogicException("The promise is already {$state}.")
+ : new \LogicException("Cannot change a {$this->state} promise to {$state}");
+ }
+
+ if ($value === $this) {
+ throw new \LogicException('Cannot fulfill or reject a promise with itself');
+ }
+
+ // Clear out the state of the promise but stash the handlers.
+ $this->state = $state;
+ $this->result = $value;
+ $handlers = $this->handlers;
+ $this->handlers = null;
+ $this->waitList = $this->waitFn = null;
+ $this->cancelFn = null;
+
+ if (!$handlers) {
+ return;
+ }
+
+ // If the value was not a settled promise or a thenable, then resolve
+ // it in the task queue using the correct ID.
+ if (!method_exists($value, 'then')) {
+ $id = $state === self::FULFILLED ? 1 : 2;
+ // It's a success, so resolve the handlers in the queue.
+ queue()->add(static function () use ($id, $value, $handlers) {
+ foreach ($handlers as $handler) {
+ self::callHandler($id, $value, $handler);
+ }
+ });
+ } elseif ($value instanceof Promise
+ && $value->getState() === self::PENDING
+ ) {
+ // We can just merge our handlers onto the next promise.
+ $value->handlers = array_merge($value->handlers, $handlers);
+ } else {
+ // Resolve the handlers when the forwarded promise is resolved.
+ $value->then(
+ static function ($value) use ($handlers) {
+ foreach ($handlers as $handler) {
+ self::callHandler(1, $value, $handler);
+ }
+ },
+ static function ($reason) use ($handlers) {
+ foreach ($handlers as $handler) {
+ self::callHandler(2, $reason, $handler);
+ }
+ }
+ );
+ }
+ }
+
+ /**
+ * Call a stack of handlers using a specific callback index and value.
+ *
+ * @param int $index 1 (resolve) or 2 (reject).
+ * @param mixed $value Value to pass to the callback.
+ * @param array $handler Array of handler data (promise and callbacks).
+ *
+ * @return array Returns the next group to resolve.
+ */
+ private static function callHandler($index, $value, array $handler)
+ {
+ /** @var PromiseInterface $promise */
+ $promise = $handler[0];
+
+ // The promise may have been cancelled or resolved before placing
+ // this thunk in the queue.
+ if ($promise->getState() !== self::PENDING) {
+ return;
+ }
+
+ try {
+ if (isset($handler[$index])) {
+ $promise->resolve($handler[$index]($value));
+ } elseif ($index === 1) {
+ // Forward resolution values as-is.
+ $promise->resolve($value);
+ } else {
+ // Forward rejections down the chain.
+ $promise->reject($value);
+ }
+ } catch (\Exception $reason) {
+ $promise->reject($reason);
+ }
+ }
+
+ private function waitIfPending()
+ {
+ if ($this->state !== self::PENDING) {
+ return;
+ } elseif ($this->waitFn) {
+ $this->invokeWaitFn();
+ } elseif ($this->waitList) {
+ $this->invokeWaitList();
+ } else {
+ // If there's not wait function, then reject the promise.
+ $this->reject('Cannot wait on a promise that has '
+ . 'no internal wait function. You must provide a wait '
+ . 'function when constructing the promise to be able to '
+ . 'wait on a promise.');
+ }
+
+ queue()->run();
+
+ if ($this->state === self::PENDING) {
+ $this->reject('Invoking the wait callback did not resolve the promise');
+ }
+ }
+
+ private function invokeWaitFn()
+ {
+ try {
+ $wfn = $this->waitFn;
+ $this->waitFn = null;
+ $wfn(true);
+ } catch (\Exception $reason) {
+ if ($this->state === self::PENDING) {
+ // The promise has not been resolved yet, so reject the promise
+ // with the exception.
+ $this->reject($reason);
+ } else {
+ // The promise was already resolved, so there's a problem in
+ // the application.
+ throw $reason;
+ }
+ }
+ }
+
+ private function invokeWaitList()
+ {
+ $waitList = $this->waitList;
+ $this->waitList = null;
+
+ foreach ($waitList as $result) {
+ descend:
+ $result->waitIfPending();
+ if ($result->result instanceof Promise) {
+ $result = $result->result;
+ goto descend;
+ }
+ }
+ }
+}
diff --git a/server/vendor/guzzlehttp/promises/src/PromiseInterface.php b/server/vendor/guzzlehttp/promises/src/PromiseInterface.php
new file mode 100644
index 0000000..8f5f4b9
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/src/PromiseInterface.php
@@ -0,0 +1,93 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * A promise represents the eventual result of an asynchronous operation.
+ *
+ * The primary way of interacting with a promise is through its then method,
+ * which registers callbacks to receive either a promise’s eventual value or
+ * the reason why the promise cannot be fulfilled.
+ *
+ * @link https://promisesaplus.com/
+ */
+interface PromiseInterface
+{
+ const PENDING = 'pending';
+ const FULFILLED = 'fulfilled';
+ const REJECTED = 'rejected';
+
+ /**
+ * Appends fulfillment and rejection handlers to the promise, and returns
+ * a new promise resolving to the return value of the called handler.
+ *
+ * @param callable $onFulfilled Invoked when the promise fulfills.
+ * @param callable $onRejected Invoked when the promise is rejected.
+ *
+ * @return PromiseInterface
+ */
+ public function then(
+ callable $onFulfilled = null,
+ callable $onRejected = null
+ );
+
+ /**
+ * Appends a rejection handler callback to the promise, and returns a new
+ * promise resolving to the return value of the callback if it is called,
+ * or to its original fulfillment value if the promise is instead
+ * fulfilled.
+ *
+ * @param callable $onRejected Invoked when the promise is rejected.
+ *
+ * @return PromiseInterface
+ */
+ public function otherwise(callable $onRejected);
+
+ /**
+ * Get the state of the promise ("pending", "rejected", or "fulfilled").
+ *
+ * The three states can be checked against the constants defined on
+ * PromiseInterface: PENDING, FULFILLED, and REJECTED.
+ *
+ * @return string
+ */
+ public function getState();
+
+ /**
+ * Resolve the promise with the given value.
+ *
+ * @param mixed $value
+ * @throws \RuntimeException if the promise is already resolved.
+ */
+ public function resolve($value);
+
+ /**
+ * Reject the promise with the given reason.
+ *
+ * @param mixed $reason
+ * @throws \RuntimeException if the promise is already resolved.
+ */
+ public function reject($reason);
+
+ /**
+ * Cancels the promise if possible.
+ *
+ * @link https://github.com/promises-aplus/cancellation-spec/issues/7
+ */
+ public function cancel();
+
+ /**
+ * Waits until the promise completes if possible.
+ *
+ * Pass $unwrap as true to unwrap the result of the promise, either
+ * returning the resolved value or throwing the rejected exception.
+ *
+ * If the promise cannot be waited on, then the promise will be rejected.
+ *
+ * @param bool $unwrap
+ *
+ * @return mixed
+ * @throws \LogicException if the promise has no wait function or if the
+ * promise does not settle after waiting.
+ */
+ public function wait($unwrap = true);
+}
diff --git a/server/vendor/guzzlehttp/promises/src/PromisorInterface.php b/server/vendor/guzzlehttp/promises/src/PromisorInterface.php
new file mode 100644
index 0000000..b07fe32
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/src/PromisorInterface.php
@@ -0,0 +1,15 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * Interface used with classes that return a promise.
+ */
+interface PromisorInterface
+{
+ /**
+ * Returns a promise.
+ *
+ * @return PromiseInterface
+ */
+ public function promise();
+}
diff --git a/server/vendor/guzzlehttp/promises/src/RejectedPromise.php b/server/vendor/guzzlehttp/promises/src/RejectedPromise.php
new file mode 100644
index 0000000..bd499e6
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/src/RejectedPromise.php
@@ -0,0 +1,84 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * A promise that has been rejected.
+ *
+ * Thenning off of this promise will invoke the onRejected callback
+ * immediately and ignore other callbacks.
+ */
+class RejectedPromise implements PromiseInterface
+{
+ private $reason;
+
+ public function __construct($reason)
+ {
+ if (method_exists($reason, 'then')) {
+ throw new \InvalidArgumentException(
+ 'You cannot create a RejectedPromise with a promise.');
+ }
+
+ $this->reason = $reason;
+ }
+
+ public function then(
+ callable $onFulfilled = null,
+ callable $onRejected = null
+ ) {
+ // If there's no onRejected callback then just return self.
+ if (!$onRejected) {
+ return $this;
+ }
+
+ $queue = queue();
+ $reason = $this->reason;
+ $p = new Promise([$queue, 'run']);
+ $queue->add(static function () use ($p, $reason, $onRejected) {
+ if ($p->getState() === self::PENDING) {
+ try {
+ // Return a resolved promise if onRejected does not throw.
+ $p->resolve($onRejected($reason));
+ } catch (\Exception $e) {
+ // onRejected threw, so return a rejected promise.
+ $p->reject($e);
+ }
+ }
+ });
+
+ return $p;
+ }
+
+ public function otherwise(callable $onRejected)
+ {
+ return $this->then(null, $onRejected);
+ }
+
+ public function wait($unwrap = true, $defaultDelivery = null)
+ {
+ if ($unwrap) {
+ throw exception_for($this->reason);
+ }
+ }
+
+ public function getState()
+ {
+ return self::REJECTED;
+ }
+
+ public function resolve($value)
+ {
+ throw new \LogicException("Cannot resolve a rejected promise");
+ }
+
+ public function reject($reason)
+ {
+ if ($reason !== $this->reason) {
+ throw new \LogicException("Cannot reject a rejected promise");
+ }
+ }
+
+ public function cancel()
+ {
+ // pass
+ }
+}
diff --git a/server/vendor/guzzlehttp/promises/src/RejectionException.php b/server/vendor/guzzlehttp/promises/src/RejectionException.php
new file mode 100644
index 0000000..07c1136
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/src/RejectionException.php
@@ -0,0 +1,47 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * A special exception that is thrown when waiting on a rejected promise.
+ *
+ * The reason value is available via the getReason() method.
+ */
+class RejectionException extends \RuntimeException
+{
+ /** @var mixed Rejection reason. */
+ private $reason;
+
+ /**
+ * @param mixed $reason Rejection reason.
+ * @param string $description Optional description
+ */
+ public function __construct($reason, $description = null)
+ {
+ $this->reason = $reason;
+
+ $message = 'The promise was rejected';
+
+ if ($description) {
+ $message .= ' with reason: ' . $description;
+ } elseif (is_string($reason)
+ || (is_object($reason) && method_exists($reason, '__toString'))
+ ) {
+ $message .= ' with reason: ' . $this->reason;
+ } elseif ($reason instanceof \JsonSerializable) {
+ $message .= ' with reason: '
+ . json_encode($this->reason, JSON_PRETTY_PRINT);
+ }
+
+ parent::__construct($message);
+ }
+
+ /**
+ * Returns the rejection reason.
+ *
+ * @return mixed
+ */
+ public function getReason()
+ {
+ return $this->reason;
+ }
+}
diff --git a/server/vendor/guzzlehttp/promises/src/TaskQueue.php b/server/vendor/guzzlehttp/promises/src/TaskQueue.php
new file mode 100644
index 0000000..5026363
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/src/TaskQueue.php
@@ -0,0 +1,79 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * A task queue that executes tasks in a FIFO order.
+ *
+ * This task queue class is used to settle promises asynchronously and
+ * maintains a constant stack size. You can use the task queue asynchronously
+ * by calling the `run()` function of the global task queue in an event loop.
+ *
+ * GuzzleHttp\Promise\queue()->run();
+ */
+class TaskQueue
+{
+ private $enableShutdown = true;
+ private $queue = [];
+
+ public function __construct($withShutdown = true)
+ {
+ if ($withShutdown) {
+ register_shutdown_function(function () {
+ if ($this->enableShutdown) {
+ // Only run the tasks if an E_ERROR didn't occur.
+ $err = error_get_last();
+ if (!$err || ($err['type'] ^ E_ERROR)) {
+ $this->run();
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * Returns true if the queue is empty.
+ *
+ * @return bool
+ */
+ public function isEmpty()
+ {
+ return !$this->queue;
+ }
+
+ /**
+ * Adds a task to the queue that will be executed the next time run is
+ * called.
+ *
+ * @param callable $task
+ */
+ public function add(callable $task)
+ {
+ $this->queue[] = $task;
+ }
+
+ /**
+ * Execute all of the pending task in the queue.
+ */
+ public function run()
+ {
+ while ($task = array_shift($this->queue)) {
+ $task();
+ }
+ }
+
+ /**
+ * The task queue will be run and exhausted by default when the process
+ * exits IFF the exit is not the result of a PHP E_ERROR error.
+ *
+ * You can disable running the automatic shutdown of the queue by calling
+ * this function. If you disable the task queue shutdown process, then you
+ * MUST either run the task queue (as a result of running your event loop
+ * or manually using the run() method) or wait on each outstanding promise.
+ *
+ * Note: This shutdown will occur before any destructors are triggered.
+ */
+ public function disableShutdown()
+ {
+ $this->enableShutdown = false;
+ }
+}
diff --git a/server/vendor/guzzlehttp/promises/src/functions.php b/server/vendor/guzzlehttp/promises/src/functions.php
new file mode 100644
index 0000000..89c6569
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/src/functions.php
@@ -0,0 +1,495 @@
+<?php
+namespace GuzzleHttp\Promise;
+
+/**
+ * Get the global task queue used for promise resolution.
+ *
+ * This task queue MUST be run in an event loop in order for promises to be
+ * settled asynchronously. It will be automatically run when synchronously
+ * waiting on a promise.
+ *
+ * <code>
+ * while ($eventLoop->isRunning()) {
+ * GuzzleHttp\Promise\queue()->run();
+ * }
+ * </code>
+ *
+ * @return TaskQueue
+ */
+function queue()
+{
+ static $queue;
+
+ if (!$queue) {
+ $queue = new TaskQueue();
+ }
+
+ return $queue;
+}
+
+/**
+ * Adds a function to run in the task queue when it is next `run()` and returns
+ * a promise that is fulfilled or rejected with the result.
+ *
+ * @param callable $task Task function to run.
+ *
+ * @return PromiseInterface
+ */
+function task(callable $task)
+{
+ $queue = queue();
+ $promise = new Promise([$queue, 'run']);
+ $queue->add(function () use ($task, $promise) {
+ try {
+ $promise->resolve($task());
+ } catch (\Exception $e) {
+ $promise->reject($e);
+ }
+ });
+
+ return $promise;
+}
+
+/**
+ * Creates a promise for a value if the value is not a promise.
+ *
+ * @param mixed $value Promise or value.
+ *
+ * @return PromiseInterface
+ */
+function promise_for($value)
+{
+ if ($value instanceof PromiseInterface) {
+ return $value;
+ }
+
+ // Return a Guzzle promise that shadows the given promise.
+ if (method_exists($value, 'then')) {
+ $wfn = method_exists($value, 'wait') ? [$value, 'wait'] : null;
+ $cfn = method_exists($value, 'cancel') ? [$value, 'cancel'] : null;
+ $promise = new Promise($wfn, $cfn);
+ $value->then([$promise, 'resolve'], [$promise, 'reject']);
+ return $promise;
+ }
+
+ return new FulfilledPromise($value);
+}
+
+/**
+ * Creates a rejected promise for a reason if the reason is not a promise. If
+ * the provided reason is a promise, then it is returned as-is.
+ *
+ * @param mixed $reason Promise or reason.
+ *
+ * @return PromiseInterface
+ */
+function rejection_for($reason)
+{
+ if ($reason instanceof PromiseInterface) {
+ return $reason;
+ }
+
+ return new RejectedPromise($reason);
+}
+
+/**
+ * Create an exception for a rejected promise value.
+ *
+ * @param mixed $reason
+ *
+ * @return \Exception
+ */
+function exception_for($reason)
+{
+ return $reason instanceof \Exception
+ ? $reason
+ : new RejectionException($reason);
+}
+
+/**
+ * Returns an iterator for the given value.
+ *
+ * @param mixed $value
+ *
+ * @return \Iterator
+ */
+function iter_for($value)
+{
+ if ($value instanceof \Iterator) {
+ return $value;
+ } elseif (is_array($value)) {
+ return new \ArrayIterator($value);
+ } else {
+ return new \ArrayIterator([$value]);
+ }
+}
+
+/**
+ * Synchronously waits on a promise to resolve and returns an inspection state
+ * array.
+ *
+ * Returns a state associative array containing a "state" key mapping to a
+ * valid promise state. If the state of the promise is "fulfilled", the array
+ * will contain a "value" key mapping to the fulfilled value of the promise. If
+ * the promise is rejected, the array will contain a "reason" key mapping to
+ * the rejection reason of the promise.
+ *
+ * @param PromiseInterface $promise Promise or value.
+ *
+ * @return array
+ */
+function inspect(PromiseInterface $promise)
+{
+ try {
+ return [
+ 'state' => PromiseInterface::FULFILLED,
+ 'value' => $promise->wait()
+ ];
+ } catch (RejectionException $e) {
+ return ['state' => 'rejected', 'reason' => $e->getReason()];
+ } catch (\Exception $e) {
+ return ['state' => 'rejected', 'reason' => $e];
+ }
+}
+
+/**
+ * Waits on all of the provided promises, but does not unwrap rejected promises
+ * as thrown exception.
+ *
+ * Returns an array of inspection state arrays.
+ *
+ * @param PromiseInterface[] $promises Traversable of promises to wait upon.
+ *
+ * @return array
+ * @see GuzzleHttp\Promise\inspect for the inspection state array format.
+ */
+function inspect_all($promises)
+{
+ $results = [];
+ foreach ($promises as $key => $promise) {
+ $results[$key] = inspect($promise);
+ }
+
+ return $results;
+}
+
+/**
+ * Waits on all of the provided promises and returns the fulfilled values.
+ *
+ * Returns an array that contains the value of each promise (in the same order
+ * the promises were provided). An exception is thrown if any of the promises
+ * are rejected.
+ *
+ * @param mixed $promises Iterable of PromiseInterface objects to wait on.
+ *
+ * @return array
+ * @throws \Exception on error
+ */
+function unwrap($promises)
+{
+ $results = [];
+ foreach ($promises as $key => $promise) {
+ $results[$key] = $promise->wait();
+ }
+
+ return $results;
+}
+
+/**
+ * Given an array of promises, return a promise that is fulfilled when all the
+ * items in the array are fulfilled.
+ *
+ * The promise's fulfillment value is an array with fulfillment values at
+ * respective positions to the original array. If any promise in the array
+ * rejects, the returned promise is rejected with the rejection reason.
+ *
+ * @param mixed $promises Promises or values.
+ *
+ * @return Promise
+ */
+function all($promises)
+{
+ $results = [];
+ return each(
+ $promises,
+ function ($value, $idx) use (&$results) {
+ $results[$idx] = $value;
+ },
+ function ($reason, $idx, Promise $aggregate) {
+ $aggregate->reject($reason);
+ }
+ )->then(function () use (&$results) {
+ ksort($results);
+ return $results;
+ });
+}
+
+/**
+ * Initiate a competitive race between multiple promises or values (values will
+ * become immediately fulfilled promises).
+ *
+ * When count amount of promises have been fulfilled, the returned promise is
+ * fulfilled with an array that contains the fulfillment values of the winners
+ * in order of resolution.
+ *
+ * This prommise is rejected with a {@see GuzzleHttp\Promise\AggregateException}
+ * if the number of fulfilled promises is less than the desired $count.
+ *
+ * @param int $count Total number of promises.
+ * @param mixed $promises Promises or values.
+ *
+ * @return Promise
+ */
+function some($count, $promises)
+{
+ $results = [];
+ $rejections = [];
+
+ return each(
+ $promises,
+ function ($value, $idx, PromiseInterface $p) use (&$results, $count) {
+ if ($p->getState() !== PromiseInterface::PENDING) {
+ return;
+ }
+ $results[$idx] = $value;
+ if (count($results) >= $count) {
+ $p->resolve(null);
+ }
+ },
+ function ($reason) use (&$rejections) {
+ $rejections[] = $reason;
+ }
+ )->then(
+ function () use (&$results, &$rejections, $count) {
+ if (count($results) !== $count) {
+ throw new AggregateException(
+ 'Not enough promises to fulfill count',
+ $rejections
+ );
+ }
+ ksort($results);
+ return array_values($results);
+ }
+ );
+}
+
+/**
+ * Like some(), with 1 as count. However, if the promise fulfills, the
+ * fulfillment value is not an array of 1 but the value directly.
+ *
+ * @param mixed $promises Promises or values.
+ *
+ * @return PromiseInterface
+ */
+function any($promises)
+{
+ return some(1, $promises)->then(function ($values) { return $values[0]; });
+}
+
+/**
+ * Returns a promise that is fulfilled when all of the provided promises have
+ * been fulfilled or rejected.
+ *
+ * The returned promise is fulfilled with an array of inspection state arrays.
+ *
+ * @param mixed $promises Promises or values.
+ *
+ * @return Promise
+ * @see GuzzleHttp\Promise\inspect for the inspection state array format.
+ */
+function settle($promises)
+{
+ $results = [];
+
+ return each(
+ $promises,
+ function ($value, $idx) use (&$results) {
+ $results[$idx] = ['state' => 'fulfilled', 'value' => $value];
+ },
+ function ($reason, $idx) use (&$results) {
+ $results[$idx] = ['state' => 'rejected', 'reason' => $reason];
+ }
+ )->then(function () use (&$results) {
+ ksort($results);
+ return $results;
+ });
+}
+
+/**
+ * Given an iterator that yields promises or values, returns a promise that is
+ * fulfilled with a null value when the iterator has been consumed or the
+ * aggregate promise has been fulfilled or rejected.
+ *
+ * $onFulfilled is a function that accepts the fulfilled value, iterator
+ * index, and the aggregate promise. The callback can invoke any necessary side
+ * effects and choose to resolve or reject the aggregate promise if needed.
+ *
+ * $onRejected is a function that accepts the rejection reason, iterator
+ * index, and the aggregate promise. The callback can invoke any necessary side
+ * effects and choose to resolve or reject the aggregate promise if needed.
+ *
+ * @param mixed $iterable Iterator or array to iterate over.
+ * @param callable $onFulfilled
+ * @param callable $onRejected
+ *
+ * @return Promise
+ */
+function each(
+ $iterable,
+ callable $onFulfilled = null,
+ callable $onRejected = null
+) {
+ return (new EachPromise($iterable, [
+ 'fulfilled' => $onFulfilled,
+ 'rejected' => $onRejected
+ ]))->promise();
+}
+
+/**
+ * Like each, but only allows a certain number of outstanding promises at any
+ * given time.
+ *
+ * $concurrency may be an integer or a function that accepts the number of
+ * pending promises and returns a numeric concurrency limit value to allow for
+ * dynamic a concurrency size.
+ *
+ * @param mixed $iterable
+ * @param int|callable $concurrency
+ * @param callable $onFulfilled
+ * @param callable $onRejected
+ *
+ * @return mixed
+ */
+function each_limit(
+ $iterable,
+ $concurrency,
+ callable $onFulfilled = null,
+ callable $onRejected = null
+) {
+ return (new EachPromise($iterable, [
+ 'fulfilled' => $onFulfilled,
+ 'rejected' => $onRejected,
+ 'concurrency' => $concurrency
+ ]))->promise();
+}
+
+/**
+ * Like each_limit, but ensures that no promise in the given $iterable argument
+ * is rejected. If any promise is rejected, then the aggregate promise is
+ * rejected with the encountered rejection.
+ *
+ * @param mixed $iterable
+ * @param int|callable $concurrency
+ * @param callable $onFulfilled
+ *
+ * @return mixed
+ */
+function each_limit_all(
+ $iterable,
+ $concurrency,
+ callable $onFulfilled = null
+) {
+ return each_limit(
+ $iterable,
+ $concurrency,
+ $onFulfilled,
+ function ($reason, $idx, PromiseInterface $aggregate) {
+ $aggregate->reject($reason);
+ }
+ );
+}
+
+/**
+ * Returns true if a promise is fulfilled.
+ *
+ * @param PromiseInterface $promise
+ *
+ * @return bool
+ */
+function is_fulfilled(PromiseInterface $promise)
+{
+ return $promise->getState() === PromiseInterface::FULFILLED;
+}
+
+/**
+ * Returns true if a promise is rejected.
+ *
+ * @param PromiseInterface $promise
+ *
+ * @return bool
+ */
+function is_rejected(PromiseInterface $promise)
+{
+ return $promise->getState() === PromiseInterface::REJECTED;
+}
+
+/**
+ * Returns true if a promise is fulfilled or rejected.
+ *
+ * @param PromiseInterface $promise
+ *
+ * @return bool
+ */
+function is_settled(PromiseInterface $promise)
+{
+ return $promise->getState() !== PromiseInterface::PENDING;
+}
+
+/**
+ * Creates a promise that is resolved using a generator that yields values or
+ * promises (somewhat similar to C#'s async keyword).
+ *
+ * When called, the coroutine function will start an instance of the generator
+ * and returns a promise that is fulfilled with its final yielded value.
+ *
+ * Control is returned back to the generator when the yielded promise settles.
+ * This can lead to less verbose code when doing lots of sequential async calls
+ * with minimal processing in between.
+ *
+ * use GuzzleHttp\Promise;
+ *
+ * function createPromise($value) {
+ * return new Promise\FulfilledPromise($value);
+ * }
+ *
+ * $promise = Promise\coroutine(function () {
+ * $value = (yield createPromise('a'));
+ * try {
+ * $value = (yield createPromise($value . 'b'));
+ * } catch (\Exception $e) {
+ * // The promise was rejected.
+ * }
+ * yield $value . 'c';
+ * });
+ *
+ * // Outputs "abc"
+ * $promise->then(function ($v) { echo $v; });
+ *
+ * @param callable $generatorFn Generator function to wrap into a promise.
+ *
+ * @return Promise
+ * @link https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration
+ */
+function coroutine(callable $generatorFn)
+{
+ $generator = $generatorFn();
+ return __next_coroutine($generator->current(), $generator)->then();
+}
+
+/** @internal */
+function __next_coroutine($yielded, \Generator $generator)
+{
+ return promise_for($yielded)->then(
+ function ($value) use ($generator) {
+ $nextYield = $generator->send($value);
+ return $generator->valid()
+ ? __next_coroutine($nextYield, $generator)
+ : $value;
+ },
+ function ($reason) use ($generator) {
+ $nextYield = $generator->throw(exception_for($reason));
+ // The throw was caught, so keep iterating on the coroutine
+ return __next_coroutine($nextYield, $generator);
+ }
+ );
+}
diff --git a/server/vendor/guzzlehttp/promises/src/functions_include.php b/server/vendor/guzzlehttp/promises/src/functions_include.php
new file mode 100644
index 0000000..34cd171
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/src/functions_include.php
@@ -0,0 +1,6 @@
+<?php
+
+// Don't redefine the functions if included multiple times.
+if (!function_exists('GuzzleHttp\Promise\promise_for')) {
+ require __DIR__ . '/functions.php';
+}
diff --git a/server/vendor/guzzlehttp/promises/tests/AggregateExceptionTest.php b/server/vendor/guzzlehttp/promises/tests/AggregateExceptionTest.php
new file mode 100644
index 0000000..eaa7703
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/tests/AggregateExceptionTest.php
@@ -0,0 +1,14 @@
+<?php
+namespace GuzzleHttp\Promise\Tests;
+
+use GuzzleHttp\Promise\AggregateException;
+
+class AggregateExceptionTest extends \PHPUnit_Framework_TestCase
+{
+ public function testHasReason()
+ {
+ $e = new AggregateException('foo', ['baz', 'bar']);
+ $this->assertContains('foo', $e->getMessage());
+ $this->assertEquals(['baz', 'bar'], $e->getReason());
+ }
+}
diff --git a/server/vendor/guzzlehttp/promises/tests/EachPromiseTest.php b/server/vendor/guzzlehttp/promises/tests/EachPromiseTest.php
new file mode 100644
index 0000000..0a0a851
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/tests/EachPromiseTest.php
@@ -0,0 +1,294 @@
+<?php
+namespace GuzzleHttp\Promise\Tests;
+
+use GuzzleHttp\Promise\RejectedPromise;
+use GuzzleHttp\Promise\FulfilledPromise;
+use GuzzleHttp\Promise\Promise;
+use GuzzleHttp\Promise\PromiseInterface;
+use GuzzleHttp\Promise\EachPromise;
+use GuzzleHttp\Promise as P;
+
+/**
+ * @covers GuzzleHttp\Promise\EachPromise
+ */
+class EachPromiseTest extends \PHPUnit_Framework_TestCase
+{
+ public function testReturnsSameInstance()
+ {
+ $each = new EachPromise([], ['concurrency' => 100]);
+ $this->assertSame($each->promise(), $each->promise());
+ }
+
+ public function testInvokesAllPromises()
+ {
+ $promises = [new Promise(), new Promise(), new Promise()];
+ $called = [];
+ $each = new EachPromise($promises, [
+ 'fulfilled' => function ($value) use (&$called) {
+ $called[] = $value;
+ }
+ ]);
+ $p = $each->promise();
+ $promises[0]->resolve('a');
+ $promises[1]->resolve('c');
+ $promises[2]->resolve('b');
+ P\queue()->run();
+ $this->assertEquals(['a', 'c', 'b'], $called);
+ $this->assertEquals(PromiseInterface::FULFILLED, $p->getState());
+ }
+
+ public function testIsWaitable()
+ {
+ $a = new Promise(function () use (&$a) { $a->resolve('a'); });
+ $b = new Promise(function () use (&$b) { $b->resolve('b'); });
+ $called = [];
+ $each = new EachPromise([$a, $b], [
+ 'fulfilled' => function ($value) use (&$called) { $called[] = $value; }
+ ]);
+ $p = $each->promise();
+ $this->assertNull($p->wait());
+ $this->assertEquals(PromiseInterface::FULFILLED, $p->getState());
+ $this->assertEquals(['a', 'b'], $called);
+ }
+
+ public function testCanResolveBeforeConsumingAll()
+ {
+ $called = 0;
+ $a = new Promise(function () use (&$a) { $a->resolve('a'); });
+ $b = new Promise(function () { $this->fail(); });
+ $each = new EachPromise([$a, $b], [
+ 'fulfilled' => function ($value, $idx, Promise $aggregate) use (&$called) {
+ $this->assertSame($idx, 0);
+ $this->assertEquals('a', $value);
+ $aggregate->resolve(null);
+ $called++;
+ },
+ 'rejected' => function (\Exception $reason) {
+ $this->fail($reason->getMessage());
+ }
+ ]);
+ $p = $each->promise();
+ $p->wait();
+ $this->assertNull($p->wait());
+ $this->assertEquals(1, $called);
+ $this->assertEquals(PromiseInterface::FULFILLED, $a->getState());
+ $this->assertEquals(PromiseInterface::PENDING, $b->getState());
+ // Resolving $b has no effect on the aggregate promise.
+ $b->resolve('foo');
+ $this->assertEquals(1, $called);
+ }
+
+ public function testLimitsPendingPromises()
+ {
+ $pending = [new Promise(), new Promise(), new Promise(), new Promise()];
+ $promises = new \ArrayIterator($pending);
+ $each = new EachPromise($promises, ['concurrency' => 2]);
+ $p = $each->promise();
+ $this->assertCount(2, $this->readAttribute($each, 'pending'));
+ $pending[0]->resolve('a');
+ $this->assertCount(2, $this->readAttribute($each, 'pending'));
+ $this->assertTrue($promises->valid());
+ $pending[1]->resolve('b');
+ P\queue()->run();
+ $this->assertCount(2, $this->readAttribute($each, 'pending'));
+ $this->assertTrue($promises->valid());
+ $promises[2]->resolve('c');
+ P\queue()->run();
+ $this->assertCount(1, $this->readAttribute($each, 'pending'));
+ $this->assertEquals(PromiseInterface::PENDING, $p->getState());
+ $promises[3]->resolve('d');
+ P\queue()->run();
+ $this->assertNull($this->readAttribute($each, 'pending'));
+ $this->assertEquals(PromiseInterface::FULFILLED, $p->getState());
+ $this->assertFalse($promises->valid());
+ }
+
+ public function testDynamicallyLimitsPendingPromises()
+ {
+ $calls = [];
+ $pendingFn = function ($count) use (&$calls) {
+ $calls[] = $count;
+ return 2;
+ };
+ $pending = [new Promise(), new Promise(), new Promise(), new Promise()];
+ $promises = new \ArrayIterator($pending);
+ $each = new EachPromise($promises, ['concurrency' => $pendingFn]);
+ $p = $each->promise();
+ $this->assertCount(2, $this->readAttribute($each, 'pending'));
+ $pending[0]->resolve('a');
+ $this->assertCount(2, $this->readAttribute($each, 'pending'));
+ $this->assertTrue($promises->valid());
+ $pending[1]->resolve('b');
+ $this->assertCount(2, $this->readAttribute($each, 'pending'));
+ P\queue()->run();
+ $this->assertTrue($promises->valid());
+ $promises[2]->resolve('c');
+ P\queue()->run();
+ $this->assertCount(1, $this->readAttribute($each, 'pending'));
+ $this->assertEquals(PromiseInterface::PENDING, $p->getState());
+ $promises[3]->resolve('d');
+ P\queue()->run();
+ $this->assertNull($this->readAttribute($each, 'pending'));
+ $this->assertEquals(PromiseInterface::FULFILLED, $p->getState());
+ $this->assertEquals([0, 1, 1, 1], $calls);
+ $this->assertFalse($promises->valid());
+ }
+
+ public function testClearsReferencesWhenResolved()
+ {
+ $called = false;
+ $a = new Promise(function () use (&$a, &$called) {
+ $a->resolve('a');
+ $called = true;
+ });
+ $each = new EachPromise([$a], [
+ 'concurrency' => function () { return 1; },
+ 'fulfilled' => function () {},
+ 'rejected' => function () {}
+ ]);
+ $each->promise()->wait();
+ $this->assertNull($this->readAttribute($each, 'onFulfilled'));
+ $this->assertNull($this->readAttribute($each, 'onRejected'));
+ $this->assertNull($this->readAttribute($each, 'iterable'));
+ $this->assertNull($this->readAttribute($each, 'pending'));
+ $this->assertNull($this->readAttribute($each, 'concurrency'));
+ $this->assertTrue($called);
+ }
+
+ public function testCanBeCancelled()
+ {
+ $this->markTestIncomplete();
+ }
+
+ public function testFulfillsImmediatelyWhenGivenAnEmptyIterator()
+ {
+ $each = new EachPromise(new \ArrayIterator([]));
+ $result = $each->promise()->wait();
+ }
+
+ public function testDoesNotBlowStackWithFulfilledPromises()
+ {
+ $pending = [];
+ for ($i = 0; $i < 100; $i++) {
+ $pending[] = new FulfilledPromise($i);
+ }
+ $values = [];
+ $each = new EachPromise($pending, [
+ 'fulfilled' => function ($value) use (&$values) {
+ $values[] = $value;
+ }
+ ]);
+ $called = false;
+ $each->promise()->then(function () use (&$called) {
+ $called = true;
+ });
+ $this->assertFalse($called);
+ P\queue()->run();
+ $this->assertTrue($called);
+ $this->assertEquals(range(0, 99), $values);
+ }
+
+ public function testDoesNotBlowStackWithRejectedPromises()
+ {
+ $pending = [];
+ for ($i = 0; $i < 100; $i++) {
+ $pending[] = new RejectedPromise($i);
+ }
+ $values = [];
+ $each = new EachPromise($pending, [
+ 'rejected' => function ($value) use (&$values) {
+ $values[] = $value;
+ }
+ ]);
+ $called = false;
+ $each->promise()->then(
+ function () use (&$called) { $called = true; },
+ function () { $this->fail('Should not have rejected.'); }
+ );
+ $this->assertFalse($called);
+ P\queue()->run();
+ $this->assertTrue($called);
+ $this->assertEquals(range(0, 99), $values);
+ }
+
+ public function testReturnsPromiseForWhatever()
+ {
+ $called = [];
+ $arr = ['a', 'b'];
+ $each = new EachPromise($arr, [
+ 'fulfilled' => function ($v) use (&$called) { $called[] = $v; }
+ ]);
+ $p = $each->promise();
+ $this->assertNull($p->wait());
+ $this->assertEquals(['a', 'b'], $called);
+ }
+
+ public function testRejectsAggregateWhenNextThrows()
+ {
+ $iter = function () {
+ yield 'a';
+ throw new \Exception('Failure');
+ };
+ $each = new EachPromise($iter());
+ $p = $each->promise();
+ $e = null;
+ $received = null;
+ $p->then(null, function ($reason) use (&$e) { $e = $reason; });
+ P\queue()->run();
+ $this->assertInstanceOf('Exception', $e);
+ $this->assertEquals('Failure', $e->getMessage());
+ }
+
+ public function testDoesNotCallNextOnIteratorUntilNeededWhenWaiting()
+ {
+ $results = [];
+ $values = [10];
+ $remaining = 9;
+ $iter = function () use (&$values) {
+ while ($value = array_pop($values)) {
+ yield $value;
+ }
+ };
+ $each = new EachPromise($iter(), [
+ 'concurrency' => 1,
+ 'fulfilled' => function ($r) use (&$results, &$values, &$remaining) {
+ $results[] = $r;
+ if ($remaining > 0) {
+ $values[] = $remaining--;
+ }
+ }
+ ]);
+ $each->promise()->wait();
+ $this->assertEquals(range(10, 1), $results);
+ }
+
+ public function testDoesNotCallNextOnIteratorUntilNeededWhenAsync()
+ {
+ $firstPromise = new Promise();
+ $pending = [$firstPromise];
+ $values = [$firstPromise];
+ $results = [];
+ $remaining = 9;
+ $iter = function () use (&$values) {
+ while ($value = array_pop($values)) {
+ yield $value;
+ }
+ };
+ $each = new EachPromise($iter(), [
+ 'concurrency' => 1,
+ 'fulfilled' => function ($r) use (&$results, &$values, &$remaining, &$pending) {
+ $results[] = $r;
+ if ($remaining-- > 0) {
+ $pending[] = $values[] = new Promise();
+ }
+ }
+ ]);
+ $i = 0;
+ $each->promise();
+ while ($promise = array_pop($pending)) {
+ $promise->resolve($i++);
+ P\queue()->run();
+ }
+ $this->assertEquals(range(0, 9), $results);
+ }
+}
diff --git a/server/vendor/guzzlehttp/promises/tests/FulfilledPromiseTest.php b/server/vendor/guzzlehttp/promises/tests/FulfilledPromiseTest.php
new file mode 100644
index 0000000..554c150
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/tests/FulfilledPromiseTest.php
@@ -0,0 +1,108 @@
+<?php
+namespace GuzzleHttp\Tests\Promise;
+
+use GuzzleHttp\Promise\Promise;
+use GuzzleHttp\Promise\FulfilledPromise;
+
+/**
+ * @covers GuzzleHttp\Promise\FulfilledPromise
+ */
+class FulfilledPromiseTest extends \PHPUnit_Framework_TestCase
+{
+ public function testReturnsValueWhenWaitedUpon()
+ {
+ $p = new FulfilledPromise('foo');
+ $this->assertEquals('fulfilled', $p->getState());
+ $this->assertEquals('foo', $p->wait(true));
+ }
+
+ public function testCannotCancel()
+ {
+ $p = new FulfilledPromise('foo');
+ $this->assertEquals('fulfilled', $p->getState());
+ $p->cancel();
+ $this->assertEquals('foo', $p->wait());
+ }
+
+ /**
+ * @expectedException \LogicException
+ * @exepctedExceptionMessage Cannot resolve a fulfilled promise
+ */
+ public function testCannotResolve()
+ {
+ $p = new FulfilledPromise('foo');
+ $p->resolve('bar');
+ }
+
+ /**
+ * @expectedException \LogicException
+ * @exepctedExceptionMessage Cannot reject a fulfilled promise
+ */
+ public function testCannotReject()
+ {
+ $p = new FulfilledPromise('foo');
+ $p->reject('bar');
+ }
+
+ public function testCanResolveWithSameValue()
+ {
+ $p = new FulfilledPromise('foo');
+ $p->resolve('foo');
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testCannotResolveWithPromise()
+ {
+ new FulfilledPromise(new Promise());
+ }
+
+ public function testReturnsSelfWhenNoOnFulfilled()
+ {
+ $p = new FulfilledPromise('a');
+ $this->assertSame($p, $p->then());
+ }
+
+ public function testAsynchronouslyInvokesOnFulfilled()
+ {
+ $p = new FulfilledPromise('a');
+ $r = null;
+ $f = function ($d) use (&$r) { $r = $d; };
+ $p2 = $p->then($f);
+ $this->assertNotSame($p, $p2);
+ $this->assertNull($r);
+ \GuzzleHttp\Promise\queue()->run();
+ $this->assertEquals('a', $r);
+ }
+
+ public function testReturnsNewRejectedWhenOnFulfilledFails()
+ {
+ $p = new FulfilledPromise('a');
+ $f = function () { throw new \Exception('b'); };
+ $p2 = $p->then($f);
+ $this->assertNotSame($p, $p2);
+ try {
+ $p2->wait();
+ $this->fail();
+ } catch (\Exception $e) {
+ $this->assertEquals('b', $e->getMessage());
+ }
+ }
+
+ public function testOtherwiseIsSugarForRejections()
+ {
+ $c = null;
+ $p = new FulfilledPromise('foo');
+ $p->otherwise(function ($v) use (&$c) { $c = $v; });
+ $this->assertNull($c);
+ }
+
+ public function testDoesNotTryToFulfillTwiceDuringTrampoline()
+ {
+ $fp = new FulfilledPromise('a');
+ $t1 = $fp->then(function ($v) { return $v . ' b'; });
+ $t1->resolve('why!');
+ $this->assertEquals('why!', $t1->wait());
+ }
+}
diff --git a/server/vendor/guzzlehttp/promises/tests/NotPromiseInstance.php b/server/vendor/guzzlehttp/promises/tests/NotPromiseInstance.php
new file mode 100644
index 0000000..6288aa8
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/tests/NotPromiseInstance.php
@@ -0,0 +1,50 @@
+<?php
+namespace GuzzleHttp\Promise\Tests;
+
+use GuzzleHttp\Promise\Promise;
+use GuzzleHttp\Promise\PromiseInterface;
+
+class NotPromiseInstance extends Thennable implements PromiseInterface
+{
+ private $nextPromise = null;
+
+ public function __construct()
+ {
+ $this->nextPromise = new Promise();
+ }
+
+ public function then(callable $res = null, callable $rej = null)
+ {
+ return $this->nextPromise->then($res, $rej);
+ }
+
+ public function otherwise(callable $onRejected)
+ {
+ return $this->then($onRejected);
+ }
+
+ public function resolve($value)
+ {
+ $this->nextPromise->resolve($value);
+ }
+
+ public function reject($reason)
+ {
+ $this->nextPromise->reject($reason);
+ }
+
+ public function wait($unwrap = true, $defaultResolution = null)
+ {
+
+ }
+
+ public function cancel()
+ {
+
+ }
+
+ public function getState()
+ {
+ return $this->nextPromise->getState();
+ }
+}
diff --git a/server/vendor/guzzlehttp/promises/tests/PromiseTest.php b/server/vendor/guzzlehttp/promises/tests/PromiseTest.php
new file mode 100644
index 0000000..946c627
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/tests/PromiseTest.php
@@ -0,0 +1,579 @@
+<?php
+namespace GuzzleHttp\Promise\Tests;
+
+use GuzzleHttp\Promise\CancellationException;
+use GuzzleHttp\Promise as P;
+use GuzzleHttp\Promise\Promise;
+use GuzzleHttp\Promise\RejectedPromise;
+use GuzzleHttp\Promise\RejectionException;
+
+/**
+ * @covers GuzzleHttp\Promise\Promise
+ */
+class PromiseTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException \LogicException
+ * @expectedExceptionMessage The promise is already fulfilled
+ */
+ public function testCannotResolveNonPendingPromise()
+ {
+ $p = new Promise();
+ $p->resolve('foo');
+ $p->resolve('bar');
+ $this->assertEquals('foo', $p->wait());
+ }
+
+ public function testCanResolveWithSameValue()
+ {
+ $p = new Promise();
+ $p->resolve('foo');
+ $p->resolve('foo');
+ }
+
+ /**
+ * @expectedException \LogicException
+ * @expectedExceptionMessage Cannot change a fulfilled promise to rejected
+ */
+ public function testCannotRejectNonPendingPromise()
+ {
+ $p = new Promise();
+ $p->resolve('foo');
+ $p->reject('bar');
+ $this->assertEquals('foo', $p->wait());
+ }
+
+ public function testCanRejectWithSameValue()
+ {
+ $p = new Promise();
+ $p->reject('foo');
+ $p->reject('foo');
+ }
+
+ /**
+ * @expectedException \LogicException
+ * @expectedExceptionMessage Cannot change a fulfilled promise to rejected
+ */
+ public function testCannotRejectResolveWithSameValue()
+ {
+ $p = new Promise();
+ $p->resolve('foo');
+ $p->reject('foo');
+ }
+
+ public function testInvokesWaitFunction()
+ {
+ $p = new Promise(function () use (&$p) { $p->resolve('10'); });
+ $this->assertEquals('10', $p->wait());
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Promise\RejectionException
+ */
+ public function testRejectsAndThrowsWhenWaitFailsToResolve()
+ {
+ $p = new Promise(function () {});
+ $p->wait();
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Promise\RejectionException
+ * @expectedExceptionMessage The promise was rejected with reason: foo
+ */
+ public function testThrowsWhenUnwrapIsRejectedWithNonException()
+ {
+ $p = new Promise(function () use (&$p) { $p->reject('foo'); });
+ $p->wait();
+ }
+
+ /**
+ * @expectedException \UnexpectedValueException
+ * @expectedExceptionMessage foo
+ */
+ public function testThrowsWhenUnwrapIsRejectedWithException()
+ {
+ $e = new \UnexpectedValueException('foo');
+ $p = new Promise(function () use (&$p, $e) { $p->reject($e); });
+ $p->wait();
+ }
+
+ public function testDoesNotUnwrapExceptionsWhenDisabled()
+ {
+ $p = new Promise(function () use (&$p) { $p->reject('foo'); });
+ $this->assertEquals('pending', $p->getState());
+ $p->wait(false);
+ $this->assertEquals('rejected', $p->getState());
+ }
+
+ public function testRejectsSelfWhenWaitThrows()
+ {
+ $e = new \UnexpectedValueException('foo');
+ $p = new Promise(function () use ($e) { throw $e; });
+ try {
+ $p->wait();
+ $this->fail();
+ } catch (\UnexpectedValueException $e) {
+ $this->assertEquals('rejected', $p->getState());
+ }
+ }
+
+ public function testWaitsOnNestedPromises()
+ {
+ $p = new Promise(function () use (&$p) { $p->resolve('_'); });
+ $p2 = new Promise(function () use (&$p2) { $p2->resolve('foo'); });
+ $p3 = $p->then(function () use ($p2) { return $p2; });
+ $this->assertSame('foo', $p3->wait());
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Promise\RejectionException
+ */
+ public function testThrowsWhenWaitingOnPromiseWithNoWaitFunction()
+ {
+ $p = new Promise();
+ $p->wait();
+ }
+
+ public function testThrowsWaitExceptionAfterPromiseIsResolved()
+ {
+ $p = new Promise(function () use (&$p) {
+ $p->reject('Foo!');
+ throw new \Exception('Bar?');
+ });
+
+ try {
+ $p->wait();
+ $this->fail();
+ } catch (\Exception $e) {
+ $this->assertEquals('Bar?', $e->getMessage());
+ }
+ }
+
+ public function testGetsActualWaitValueFromThen()
+ {
+ $p = new Promise(function () use (&$p) { $p->reject('Foo!'); });
+ $p2 = $p->then(null, function ($reason) {
+ return new RejectedPromise([$reason]);
+ });
+
+ try {
+ $p2->wait();
+ $this->fail('Should have thrown');
+ } catch (RejectionException $e) {
+ $this->assertEquals(['Foo!'], $e->getReason());
+ }
+ }
+
+ public function testWaitBehaviorIsBasedOnLastPromiseInChain()
+ {
+ $p3 = new Promise(function () use (&$p3) { $p3->resolve('Whoop'); });
+ $p2 = new Promise(function () use (&$p2, $p3) { $p2->reject($p3); });
+ $p = new Promise(function () use (&$p, $p2) { $p->reject($p2); });
+ $this->assertEquals('Whoop', $p->wait());
+ }
+
+ public function testCannotCancelNonPending()
+ {
+ $p = new Promise();
+ $p->resolve('foo');
+ $p->cancel();
+ $this->assertEquals('fulfilled', $p->getState());
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Promise\CancellationException
+ */
+ public function testCancelsPromiseWhenNoCancelFunction()
+ {
+ $p = new Promise();
+ $p->cancel();
+ $this->assertEquals('rejected', $p->getState());
+ $p->wait();
+ }
+
+ public function testCancelsPromiseWithCancelFunction()
+ {
+ $called = false;
+ $p = new Promise(null, function () use (&$called) { $called = true; });
+ $p->cancel();
+ $this->assertEquals('rejected', $p->getState());
+ $this->assertTrue($called);
+ }
+
+ public function testCancelsUppermostPendingPromise()
+ {
+ $called = false;
+ $p1 = new Promise(null, function () use (&$called) { $called = true; });
+ $p2 = $p1->then(function () {});
+ $p3 = $p2->then(function () {});
+ $p4 = $p3->then(function () {});
+ $p3->cancel();
+ $this->assertEquals('rejected', $p1->getState());
+ $this->assertEquals('rejected', $p2->getState());
+ $this->assertEquals('rejected', $p3->getState());
+ $this->assertEquals('pending', $p4->getState());
+ $this->assertTrue($called);
+
+ try {
+ $p3->wait();
+ $this->fail();
+ } catch (CancellationException $e) {
+ $this->assertContains('cancelled', $e->getMessage());
+ }
+
+ try {
+ $p4->wait();
+ $this->fail();
+ } catch (CancellationException $e) {
+ $this->assertContains('cancelled', $e->getMessage());
+ }
+
+ $this->assertEquals('rejected', $p4->getState());
+ }
+
+ public function testCancelsChildPromises()
+ {
+ $called1 = $called2 = $called3 = false;
+ $p1 = new Promise(null, function () use (&$called1) { $called1 = true; });
+ $p2 = new Promise(null, function () use (&$called2) { $called2 = true; });
+ $p3 = new Promise(null, function () use (&$called3) { $called3 = true; });
+ $p4 = $p2->then(function () use ($p3) { return $p3; });
+ $p5 = $p4->then(function () { $this->fail(); });
+ $p4->cancel();
+ $this->assertEquals('pending', $p1->getState());
+ $this->assertEquals('rejected', $p2->getState());
+ $this->assertEquals('rejected', $p4->getState());
+ $this->assertEquals('pending', $p5->getState());
+ $this->assertFalse($called1);
+ $this->assertTrue($called2);
+ $this->assertFalse($called3);
+ }
+
+ public function testRejectsPromiseWhenCancelFails()
+ {
+ $called = false;
+ $p = new Promise(null, function () use (&$called) {
+ $called = true;
+ throw new \Exception('e');
+ });
+ $p->cancel();
+ $this->assertEquals('rejected', $p->getState());
+ $this->assertTrue($called);
+ try {
+ $p->wait();
+ $this->fail();
+ } catch (\Exception $e) {
+ $this->assertEquals('e', $e->getMessage());
+ }
+ }
+
+ public function testCreatesPromiseWhenFulfilledAfterThen()
+ {
+ $p = new Promise();
+ $carry = null;
+ $p2 = $p->then(function ($v) use (&$carry) { $carry = $v; });
+ $this->assertNotSame($p, $p2);
+ $p->resolve('foo');
+ P\queue()->run();
+
+ $this->assertEquals('foo', $carry);
+ }
+
+ public function testCreatesPromiseWhenFulfilledBeforeThen()
+ {
+ $p = new Promise();
+ $p->resolve('foo');
+ $carry = null;
+ $p2 = $p->then(function ($v) use (&$carry) { $carry = $v; });
+ $this->assertNotSame($p, $p2);
+ $this->assertNull($carry);
+ \GuzzleHttp\Promise\queue()->run();
+ $this->assertEquals('foo', $carry);
+ }
+
+ public function testCreatesPromiseWhenFulfilledWithNoCallback()
+ {
+ $p = new Promise();
+ $p->resolve('foo');
+ $p2 = $p->then();
+ $this->assertNotSame($p, $p2);
+ $this->assertInstanceOf('GuzzleHttp\Promise\FulfilledPromise', $p2);
+ }
+
+ public function testCreatesPromiseWhenRejectedAfterThen()
+ {
+ $p = new Promise();
+ $carry = null;
+ $p2 = $p->then(null, function ($v) use (&$carry) { $carry = $v; });
+ $this->assertNotSame($p, $p2);
+ $p->reject('foo');
+ P\queue()->run();
+ $this->assertEquals('foo', $carry);
+ }
+
+ public function testCreatesPromiseWhenRejectedBeforeThen()
+ {
+ $p = new Promise();
+ $p->reject('foo');
+ $carry = null;
+ $p2 = $p->then(null, function ($v) use (&$carry) { $carry = $v; });
+ $this->assertNotSame($p, $p2);
+ $this->assertNull($carry);
+ P\queue()->run();
+ $this->assertEquals('foo', $carry);
+ }
+
+ public function testCreatesPromiseWhenRejectedWithNoCallback()
+ {
+ $p = new Promise();
+ $p->reject('foo');
+ $p2 = $p->then();
+ $this->assertNotSame($p, $p2);
+ $this->assertInstanceOf('GuzzleHttp\Promise\RejectedPromise', $p2);
+ }
+
+ public function testInvokesWaitFnsForThens()
+ {
+ $p = new Promise(function () use (&$p) { $p->resolve('a'); });
+ $p2 = $p
+ ->then(function ($v) { return $v . '-1-'; })
+ ->then(function ($v) { return $v . '2'; });
+ $this->assertEquals('a-1-2', $p2->wait());
+ }
+
+ public function testStacksThenWaitFunctions()
+ {
+ $p1 = new Promise(function () use (&$p1) { $p1->resolve('a'); });
+ $p2 = new Promise(function () use (&$p2) { $p2->resolve('b'); });
+ $p3 = new Promise(function () use (&$p3) { $p3->resolve('c'); });
+ $p4 = $p1
+ ->then(function () use ($p2) { return $p2; })
+ ->then(function () use ($p3) { return $p3; });
+ $this->assertEquals('c', $p4->wait());
+ }
+
+ public function testForwardsFulfilledDownChainBetweenGaps()
+ {
+ $p = new Promise();
+ $r = $r2 = null;
+ $p->then(null, null)
+ ->then(function ($v) use (&$r) { $r = $v; return $v . '2'; })
+ ->then(function ($v) use (&$r2) { $r2 = $v; });
+ $p->resolve('foo');
+ P\queue()->run();
+ $this->assertEquals('foo', $r);
+ $this->assertEquals('foo2', $r2);
+ }
+
+ public function testForwardsRejectedPromisesDownChainBetweenGaps()
+ {
+ $p = new Promise();
+ $r = $r2 = null;
+ $p->then(null, null)
+ ->then(null, function ($v) use (&$r) { $r = $v; return $v . '2'; })
+ ->then(function ($v) use (&$r2) { $r2 = $v; });
+ $p->reject('foo');
+ P\queue()->run();
+ $this->assertEquals('foo', $r);
+ $this->assertEquals('foo2', $r2);
+ }
+
+ public function testForwardsThrownPromisesDownChainBetweenGaps()
+ {
+ $e = new \Exception();
+ $p = new Promise();
+ $r = $r2 = null;
+ $p->then(null, null)
+ ->then(null, function ($v) use (&$r, $e) {
+ $r = $v;
+ throw $e;
+ })
+ ->then(
+ null,
+ function ($v) use (&$r2) { $r2 = $v; }
+ );
+ $p->reject('foo');
+ P\queue()->run();
+ $this->assertEquals('foo', $r);
+ $this->assertSame($e, $r2);
+ }
+
+ public function testForwardsReturnedRejectedPromisesDownChainBetweenGaps()
+ {
+ $p = new Promise();
+ $rejected = new RejectedPromise('bar');
+ $r = $r2 = null;
+ $p->then(null, null)
+ ->then(null, function ($v) use (&$r, $rejected) {
+ $r = $v;
+ return $rejected;
+ })
+ ->then(
+ null,
+ function ($v) use (&$r2) { $r2 = $v; }
+ );
+ $p->reject('foo');
+ P\queue()->run();
+ $this->assertEquals('foo', $r);
+ $this->assertEquals('bar', $r2);
+ try {
+ $p->wait();
+ } catch (RejectionException $e) {
+ $this->assertEquals('foo', $e->getReason());
+ }
+ }
+
+ public function testForwardsHandlersToNextPromise()
+ {
+ $p = new Promise();
+ $p2 = new Promise();
+ $resolved = null;
+ $p
+ ->then(function ($v) use ($p2) { return $p2; })
+ ->then(function ($value) use (&$resolved) { $resolved = $value; });
+ $p->resolve('a');
+ $p2->resolve('b');
+ P\queue()->run();
+ $this->assertEquals('b', $resolved);
+ }
+
+ public function testRemovesReferenceFromChildWhenParentWaitedUpon()
+ {
+ $r = null;
+ $p = new Promise(function () use (&$p) { $p->resolve('a'); });
+ $p2 = new Promise(function () use (&$p2) { $p2->resolve('b'); });
+ $pb = $p->then(
+ function ($v) use ($p2, &$r) {
+ $r = $v;
+ return $p2;
+ })
+ ->then(function ($v) { return $v . '.'; });
+ $this->assertEquals('a', $p->wait());
+ $this->assertEquals('b', $p2->wait());
+ $this->assertEquals('b.', $pb->wait());
+ $this->assertEquals('a', $r);
+ }
+
+ public function testForwardsHandlersWhenFulfilledPromiseIsReturned()
+ {
+ $res = [];
+ $p = new Promise();
+ $p2 = new Promise();
+ $p2->resolve('foo');
+ $p2->then(function ($v) use (&$res) { $res[] = 'A:' . $v; });
+ // $res is A:foo
+ $p
+ ->then(function () use ($p2, &$res) { $res[] = 'B'; return $p2; })
+ ->then(function ($v) use (&$res) { $res[] = 'C:' . $v; });
+ $p->resolve('a');
+ $p->then(function ($v) use (&$res) { $res[] = 'D:' . $v; });
+ P\queue()->run();
+ $this->assertEquals(['A:foo', 'B', 'D:a', 'C:foo'], $res);
+ }
+
+ public function testForwardsHandlersWhenRejectedPromiseIsReturned()
+ {
+ $res = [];
+ $p = new Promise();
+ $p2 = new Promise();
+ $p2->reject('foo');
+ $p2->then(null, function ($v) use (&$res) { $res[] = 'A:' . $v; });
+ $p->then(null, function () use ($p2, &$res) { $res[] = 'B'; return $p2; })
+ ->then(null, function ($v) use (&$res) { $res[] = 'C:' . $v; });
+ $p->reject('a');
+ $p->then(null, function ($v) use (&$res) { $res[] = 'D:' . $v; });
+ P\queue()->run();
+ $this->assertEquals(['A:foo', 'B', 'D:a', 'C:foo'], $res);
+ }
+
+ public function testDoesNotForwardRejectedPromise()
+ {
+ $res = [];
+ $p = new Promise();
+ $p2 = new Promise();
+ $p2->cancel();
+ $p2->then(function ($v) use (&$res) { $res[] = "B:$v"; return $v; });
+ $p->then(function ($v) use ($p2, &$res) { $res[] = "B:$v"; return $p2; })
+ ->then(function ($v) use (&$res) { $res[] = 'C:' . $v; });
+ $p->resolve('a');
+ $p->then(function ($v) use (&$res) { $res[] = 'D:' . $v; });
+ P\queue()->run();
+ $this->assertEquals(['B:a', 'D:a'], $res);
+ }
+
+ public function testRecursivelyForwardsWhenOnlyThennable()
+ {
+ $res = [];
+ $p = new Promise();
+ $p2 = new Thennable();
+ $p2->resolve('foo');
+ $p2->then(function ($v) use (&$res) { $res[] = 'A:' . $v; });
+ $p->then(function () use ($p2, &$res) { $res[] = 'B'; return $p2; })
+ ->then(function ($v) use (&$res) { $res[] = 'C:' . $v; });
+ $p->resolve('a');
+ $p->then(function ($v) use (&$res) { $res[] = 'D:' . $v; });
+ P\queue()->run();
+ $this->assertEquals(['A:foo', 'B', 'D:a', 'C:foo'], $res);
+ }
+
+ public function testRecursivelyForwardsWhenNotInstanceOfPromise()
+ {
+ $res = [];
+ $p = new Promise();
+ $p2 = new NotPromiseInstance();
+ $p2->then(function ($v) use (&$res) { $res[] = 'A:' . $v; });
+ $p->then(function () use ($p2, &$res) { $res[] = 'B'; return $p2; })
+ ->then(function ($v) use (&$res) { $res[] = 'C:' . $v; });
+ $p->resolve('a');
+ $p->then(function ($v) use (&$res) { $res[] = 'D:' . $v; });
+ P\queue()->run();
+ $this->assertEquals(['B', 'D:a'], $res);
+ $p2->resolve('foo');
+ P\queue()->run();
+ $this->assertEquals(['B', 'D:a', 'A:foo', 'C:foo'], $res);
+ }
+
+ /**
+ * @expectedException \LogicException
+ * @expectedExceptionMessage Cannot fulfill or reject a promise with itself
+ */
+ public function testCannotResolveWithSelf()
+ {
+ $p = new Promise();
+ $p->resolve($p);
+ }
+
+ /**
+ * @expectedException \LogicException
+ * @expectedExceptionMessage Cannot fulfill or reject a promise with itself
+ */
+ public function testCannotRejectWithSelf()
+ {
+ $p = new Promise();
+ $p->reject($p);
+ }
+
+ public function testDoesNotBlowStackWhenWaitingOnNestedThens()
+ {
+ $inner = new Promise(function () use (&$inner) { $inner->resolve(0); });
+ $prev = $inner;
+ for ($i = 1; $i < 100; $i++) {
+ $prev = $prev->then(function ($i) { return $i + 1; });
+ }
+
+ $parent = new Promise(function () use (&$parent, $prev) {
+ $parent->resolve($prev);
+ });
+
+ $this->assertEquals(99, $parent->wait());
+ }
+
+ public function testOtherwiseIsSugarForRejections()
+ {
+ $p = new Promise();
+ $p->reject('foo');
+ $p->otherwise(function ($v) use (&$c) { $c = $v; });
+ P\queue()->run();
+ $this->assertEquals($c, 'foo');
+ }
+}
diff --git a/server/vendor/guzzlehttp/promises/tests/RejectedPromiseTest.php b/server/vendor/guzzlehttp/promises/tests/RejectedPromiseTest.php
new file mode 100644
index 0000000..60f926e
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/tests/RejectedPromiseTest.php
@@ -0,0 +1,143 @@
+<?php
+namespace GuzzleHttp\Promise\Tests;
+
+use GuzzleHttp\Promise\Promise;
+use GuzzleHttp\Promise\RejectedPromise;
+
+/**
+ * @covers GuzzleHttp\Promise\RejectedPromise
+ */
+class RejectedPromiseTest extends \PHPUnit_Framework_TestCase
+{
+ public function testThrowsReasonWhenWaitedUpon()
+ {
+ $p = new RejectedPromise('foo');
+ $this->assertEquals('rejected', $p->getState());
+ try {
+ $p->wait(true);
+ $this->fail();
+ } catch (\Exception $e) {
+ $this->assertEquals('rejected', $p->getState());
+ $this->assertContains('foo', $e->getMessage());
+ }
+ }
+
+ public function testCannotCancel()
+ {
+ $p = new RejectedPromise('foo');
+ $p->cancel();
+ $this->assertEquals('rejected', $p->getState());
+ }
+
+ /**
+ * @expectedException \LogicException
+ * @exepctedExceptionMessage Cannot resolve a rejected promise
+ */
+ public function testCannotResolve()
+ {
+ $p = new RejectedPromise('foo');
+ $p->resolve('bar');
+ }
+
+ /**
+ * @expectedException \LogicException
+ * @exepctedExceptionMessage Cannot reject a rejected promise
+ */
+ public function testCannotReject()
+ {
+ $p = new RejectedPromise('foo');
+ $p->reject('bar');
+ }
+
+ public function testCanRejectWithSameValue()
+ {
+ $p = new RejectedPromise('foo');
+ $p->reject('foo');
+ }
+
+ public function testThrowsSpecificException()
+ {
+ $e = new \Exception();
+ $p = new RejectedPromise($e);
+ try {
+ $p->wait(true);
+ $this->fail();
+ } catch (\Exception $e2) {
+ $this->assertSame($e, $e2);
+ }
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testCannotResolveWithPromise()
+ {
+ new RejectedPromise(new Promise());
+ }
+
+ public function testReturnsSelfWhenNoOnReject()
+ {
+ $p = new RejectedPromise('a');
+ $this->assertSame($p, $p->then());
+ }
+
+ public function testInvokesOnRejectedAsynchronously()
+ {
+ $p = new RejectedPromise('a');
+ $r = null;
+ $f = function ($reason) use (&$r) { $r = $reason; };
+ $p->then(null, $f);
+ $this->assertNull($r);
+ \GuzzleHttp\Promise\queue()->run();
+ $this->assertEquals('a', $r);
+ }
+
+ public function testReturnsNewRejectedWhenOnRejectedFails()
+ {
+ $p = new RejectedPromise('a');
+ $f = function () { throw new \Exception('b'); };
+ $p2 = $p->then(null, $f);
+ $this->assertNotSame($p, $p2);
+ try {
+ $p2->wait();
+ $this->fail();
+ } catch (\Exception $e) {
+ $this->assertEquals('b', $e->getMessage());
+ }
+ }
+
+ public function testWaitingIsNoOp()
+ {
+ $p = new RejectedPromise('a');
+ $p->wait(false);
+ }
+
+ public function testOtherwiseIsSugarForRejections()
+ {
+ $p = new RejectedPromise('foo');
+ $p->otherwise(function ($v) use (&$c) { $c = $v; });
+ \GuzzleHttp\Promise\queue()->run();
+ $this->assertSame('foo', $c);
+ }
+
+ public function testCanResolveThenWithSuccess()
+ {
+ $actual = null;
+ $p = new RejectedPromise('foo');
+ $p->otherwise(function ($v) {
+ return $v . ' bar';
+ })->then(function ($v) use (&$actual) {
+ $actual = $v;
+ });
+ \GuzzleHttp\Promise\queue()->run();
+ $this->assertEquals('foo bar', $actual);
+ }
+
+ public function testDoesNotTryToRejectTwiceDuringTrampoline()
+ {
+ $fp = new RejectedPromise('a');
+ $t1 = $fp->then(null, function ($v) { return $v . ' b'; });
+ $t1->resolve('why!');
+ $this->assertEquals('why!', $t1->wait());
+ }
+}
diff --git a/server/vendor/guzzlehttp/promises/tests/RejectionExceptionTest.php b/server/vendor/guzzlehttp/promises/tests/RejectionExceptionTest.php
new file mode 100644
index 0000000..36c6a88
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/tests/RejectionExceptionTest.php
@@ -0,0 +1,47 @@
+<?php
+namespace GuzzleHttp\Promise\Tests;
+
+use GuzzleHttp\Promise\RejectionException;
+
+class Thing1
+{
+ public function __construct($message)
+ {
+ $this->message = $message;
+ }
+
+ public function __toString()
+ {
+ return $this->message;
+ }
+}
+
+class Thing2 implements \JsonSerializable
+{
+ public function jsonSerialize()
+ {
+ return '{}';
+ }
+}
+
+/**
+ * @covers GuzzleHttp\Promise\RejectionException
+ */
+class RejectionExceptionTest extends \PHPUnit_Framework_TestCase
+{
+ public function testCanGetReasonFromException()
+ {
+ $thing = new Thing1('foo');
+ $e = new RejectionException($thing);
+
+ $this->assertSame($thing, $e->getReason());
+ $this->assertEquals('The promise was rejected with reason: foo', $e->getMessage());
+ }
+
+ public function testCanGetReasonMessageFromJson()
+ {
+ $reason = new Thing2();
+ $e = new RejectionException($reason);
+ $this->assertContains("{}", $e->getMessage());
+ }
+}
diff --git a/server/vendor/guzzlehttp/promises/tests/TaskQueueTest.php b/server/vendor/guzzlehttp/promises/tests/TaskQueueTest.php
new file mode 100644
index 0000000..845b263
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/tests/TaskQueueTest.php
@@ -0,0 +1,31 @@
+<?php
+namespace GuzzleHttp\Promise\Test;
+
+use GuzzleHttp\Promise\TaskQueue;
+
+class TaskQueueTest extends \PHPUnit_Framework_TestCase
+{
+ public function testKnowsIfEmpty()
+ {
+ $tq = new TaskQueue(false);
+ $this->assertTrue($tq->isEmpty());
+ }
+
+ public function testKnowsIfFull()
+ {
+ $tq = new TaskQueue(false);
+ $tq->add(function () {});
+ $this->assertFalse($tq->isEmpty());
+ }
+
+ public function testExecutesTasksInOrder()
+ {
+ $tq = new TaskQueue(false);
+ $called = [];
+ $tq->add(function () use (&$called) { $called[] = 'a'; });
+ $tq->add(function () use (&$called) { $called[] = 'b'; });
+ $tq->add(function () use (&$called) { $called[] = 'c'; });
+ $tq->run();
+ $this->assertEquals(['a', 'b', 'c'], $called);
+ }
+}
diff --git a/server/vendor/guzzlehttp/promises/tests/Thennable.php b/server/vendor/guzzlehttp/promises/tests/Thennable.php
new file mode 100644
index 0000000..398954d
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/tests/Thennable.php
@@ -0,0 +1,24 @@
+<?php
+namespace GuzzleHttp\Promise\Tests;
+
+use GuzzleHttp\Promise\Promise;
+
+class Thennable
+{
+ private $nextPromise = null;
+
+ public function __construct()
+ {
+ $this->nextPromise = new Promise();
+ }
+
+ public function then(callable $res = null, callable $rej = null)
+ {
+ return $this->nextPromise->then($res, $rej);
+ }
+
+ public function resolve($value)
+ {
+ $this->nextPromise->resolve($value);
+ }
+}
diff --git a/server/vendor/guzzlehttp/promises/tests/bootstrap.php b/server/vendor/guzzlehttp/promises/tests/bootstrap.php
new file mode 100644
index 0000000..a63d264
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/tests/bootstrap.php
@@ -0,0 +1,4 @@
+<?php
+require __DIR__ . '/../vendor/autoload.php';
+require __DIR__ . '/Thennable.php';
+require __DIR__ . '/NotPromiseInstance.php';
diff --git a/server/vendor/guzzlehttp/promises/tests/functionsTest.php b/server/vendor/guzzlehttp/promises/tests/functionsTest.php
new file mode 100644
index 0000000..8e6fcf4
--- /dev/null
+++ b/server/vendor/guzzlehttp/promises/tests/functionsTest.php
@@ -0,0 +1,694 @@
+<?php
+namespace GuzzleHttp\Promise\Tests;
+
+use GuzzleHttp\Promise as P;
+use GuzzleHttp\Promise\FulfilledPromise;
+use GuzzleHttp\Promise\Promise;
+use GuzzleHttp\Promise\RejectedPromise;
+
+class FunctionsTest extends \PHPUnit_Framework_TestCase
+{
+ public function testCreatesPromiseForValue()
+ {
+ $p = \GuzzleHttp\Promise\promise_for('foo');
+ $this->assertInstanceOf('GuzzleHttp\Promise\FulfilledPromise', $p);
+ }
+
+ public function testReturnsPromiseForPromise()
+ {
+ $p = new Promise();
+ $this->assertSame($p, \GuzzleHttp\Promise\promise_for($p));
+ }
+
+ public function testReturnsPromiseForThennable()
+ {
+ $p = new Thennable();
+ $wrapped = \GuzzleHttp\Promise\promise_for($p);
+ $this->assertNotSame($p, $wrapped);
+ $this->assertInstanceOf('GuzzleHttp\Promise\PromiseInterface', $wrapped);
+ $p->resolve('foo');
+ P\queue()->run();
+ $this->assertEquals('foo', $wrapped->wait());
+ }
+
+ public function testReturnsRejection()
+ {
+ $p = \GuzzleHttp\Promise\rejection_for('fail');
+ $this->assertInstanceOf('GuzzleHttp\Promise\RejectedPromise', $p);
+ $this->assertEquals('fail', $this->readAttribute($p, 'reason'));
+ }
+
+ public function testReturnsPromisesAsIsInRejectionFor()
+ {
+ $a = new Promise();
+ $b = \GuzzleHttp\Promise\rejection_for($a);
+ $this->assertSame($a, $b);
+ }
+
+ public function testWaitsOnAllPromisesIntoArray()
+ {
+ $e = new \Exception();
+ $a = new Promise(function () use (&$a) { $a->resolve('a'); });
+ $b = new Promise(function () use (&$b) { $b->reject('b'); });
+ $c = new Promise(function () use (&$c, $e) { $c->reject($e); });
+ $results = \GuzzleHttp\Promise\inspect_all([$a, $b, $c]);
+ $this->assertEquals([
+ ['state' => 'fulfilled', 'value' => 'a'],
+ ['state' => 'rejected', 'reason' => 'b'],
+ ['state' => 'rejected', 'reason' => $e]
+ ], $results);
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Promise\RejectionException
+ */
+ public function testUnwrapsPromisesWithNoDefaultAndFailure()
+ {
+ $promises = [new FulfilledPromise('a'), new Promise()];
+ \GuzzleHttp\Promise\unwrap($promises);
+ }
+
+ public function testUnwrapsPromisesWithNoDefault()
+ {
+ $promises = [new FulfilledPromise('a')];
+ $this->assertEquals(['a'], \GuzzleHttp\Promise\unwrap($promises));
+ }
+
+ public function testUnwrapsPromisesWithKeys()
+ {
+ $promises = [
+ 'foo' => new FulfilledPromise('a'),
+ 'bar' => new FulfilledPromise('b'),
+ ];
+ $this->assertEquals([
+ 'foo' => 'a',
+ 'bar' => 'b'
+ ], \GuzzleHttp\Promise\unwrap($promises));
+ }
+
+ public function testAllAggregatesSortedArray()
+ {
+ $a = new Promise();
+ $b = new Promise();
+ $c = new Promise();
+ $d = \GuzzleHttp\Promise\all([$a, $b, $c]);
+ $b->resolve('b');
+ $a->resolve('a');
+ $c->resolve('c');
+ $d->then(
+ function ($value) use (&$result) { $result = $value; },
+ function ($reason) use (&$result) { $result = $reason; }
+ );
+ P\queue()->run();
+ $this->assertEquals(['a', 'b', 'c'], $result);
+ }
+
+ public function testAllThrowsWhenAnyRejected()
+ {
+ $a = new Promise();
+ $b = new Promise();
+ $c = new Promise();
+ $d = \GuzzleHttp\Promise\all([$a, $b, $c]);
+ $b->resolve('b');
+ $a->reject('fail');
+ $c->resolve('c');
+ $d->then(
+ function ($value) use (&$result) { $result = $value; },
+ function ($reason) use (&$result) { $result = $reason; }
+ );
+ P\queue()->run();
+ $this->assertEquals('fail', $result);
+ }
+
+ public function testSomeAggregatesSortedArrayWithMax()
+ {
+ $a = new Promise();
+ $b = new Promise();
+ $c = new Promise();
+ $d = \GuzzleHttp\Promise\some(2, [$a, $b, $c]);
+ $b->resolve('b');
+ $c->resolve('c');
+ $a->resolve('a');
+ $d->then(function ($value) use (&$result) { $result = $value; });
+ P\queue()->run();
+ $this->assertEquals(['b', 'c'], $result);
+ }
+
+ public function testSomeRejectsWhenTooManyRejections()
+ {
+ $a = new Promise();
+ $b = new Promise();
+ $d = \GuzzleHttp\Promise\some(2, [$a, $b]);
+ $a->reject('bad');
+ $b->resolve('good');
+ P\queue()->run();
+ $this->assertEquals($a::REJECTED, $d->getState());
+ $d->then(null, function ($reason) use (&$called) {
+ $called = $reason;
+ });
+ P\queue()->run();
+ $this->assertInstanceOf('GuzzleHttp\Promise\AggregateException', $called);
+ $this->assertContains('bad', $called->getReason());
+ }
+
+ public function testCanWaitUntilSomeCountIsSatisfied()
+ {
+ $a = new Promise(function () use (&$a) { $a->resolve('a'); });
+ $b = new Promise(function () use (&$b) { $b->resolve('b'); });
+ $c = new Promise(function () use (&$c) { $c->resolve('c'); });
+ $d = \GuzzleHttp\Promise\some(2, [$a, $b, $c]);
+ $this->assertEquals(['a', 'b'], $d->wait());
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Promise\AggregateException
+ * @expectedExceptionMessage Not enough promises to fulfill count
+ */
+ public function testThrowsIfImpossibleToWaitForSomeCount()
+ {
+ $a = new Promise(function () use (&$a) { $a->resolve('a'); });
+ $d = \GuzzleHttp\Promise\some(2, [$a]);
+ $d->wait();
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Promise\AggregateException
+ * @expectedExceptionMessage Not enough promises to fulfill count
+ */
+ public function testThrowsIfResolvedWithoutCountTotalResults()
+ {
+ $a = new Promise();
+ $b = new Promise();
+ $d = \GuzzleHttp\Promise\some(3, [$a, $b]);
+ $a->resolve('a');
+ $b->resolve('b');
+ $d->wait();
+ }
+
+ public function testAnyReturnsFirstMatch()
+ {
+ $a = new Promise();
+ $b = new Promise();
+ $c = \GuzzleHttp\Promise\any([$a, $b]);
+ $b->resolve('b');
+ $a->resolve('a');
+ //P\queue()->run();
+ //$this->assertEquals('fulfilled', $c->getState());
+ $c->then(function ($value) use (&$result) { $result = $value; });
+ P\queue()->run();
+ $this->assertEquals('b', $result);
+ }
+
+ public function testSettleFulfillsWithFulfilledAndRejected()
+ {
+ $a = new Promise();
+ $b = new Promise();
+ $c = new Promise();
+ $d = \GuzzleHttp\Promise\settle([$a, $b, $c]);
+ $b->resolve('b');
+ $c->resolve('c');
+ $a->reject('a');
+ P\queue()->run();
+ $this->assertEquals('fulfilled', $d->getState());
+ $d->then(function ($value) use (&$result) { $result = $value; });
+ P\queue()->run();
+ $this->assertEquals([
+ ['state' => 'rejected', 'reason' => 'a'],
+ ['state' => 'fulfilled', 'value' => 'b'],
+ ['state' => 'fulfilled', 'value' => 'c']
+ ], $result);
+ }
+
+ public function testCanInspectFulfilledPromise()
+ {
+ $p = new FulfilledPromise('foo');
+ $this->assertEquals([
+ 'state' => 'fulfilled',
+ 'value' => 'foo'
+ ], \GuzzleHttp\Promise\inspect($p));
+ }
+
+ public function testCanInspectRejectedPromise()
+ {
+ $p = new RejectedPromise('foo');
+ $this->assertEquals([
+ 'state' => 'rejected',
+ 'reason' => 'foo'
+ ], \GuzzleHttp\Promise\inspect($p));
+ }
+
+ public function testCanInspectRejectedPromiseWithNormalException()
+ {
+ $e = new \Exception('foo');
+ $p = new RejectedPromise($e);
+ $this->assertEquals([
+ 'state' => 'rejected',
+ 'reason' => $e
+ ], \GuzzleHttp\Promise\inspect($p));
+ }
+
+ public function testCallsEachLimit()
+ {
+ $p = new Promise();
+ $aggregate = \GuzzleHttp\Promise\each_limit($p, 2);
+ $p->resolve('a');
+ P\queue()->run();
+ $this->assertEquals($p::FULFILLED, $aggregate->getState());
+ }
+
+ public function testEachLimitAllRejectsOnFailure()
+ {
+ $p = [new FulfilledPromise('a'), new RejectedPromise('b')];
+ $aggregate = \GuzzleHttp\Promise\each_limit_all($p, 2);
+ P\queue()->run();
+ $this->assertEquals(P\PromiseInterface::REJECTED, $aggregate->getState());
+ $result = \GuzzleHttp\Promise\inspect($aggregate);
+ $this->assertEquals('b', $result['reason']);
+ }
+
+ public function testIterForReturnsIterator()
+ {
+ $iter = new \ArrayIterator();
+ $this->assertSame($iter, \GuzzleHttp\Promise\iter_for($iter));
+ }
+
+ public function testKnowsIfFulfilled()
+ {
+ $p = new FulfilledPromise(null);
+ $this->assertTrue(P\is_fulfilled($p));
+ $this->assertFalse(P\is_rejected($p));
+ }
+
+ public function testKnowsIfRejected()
+ {
+ $p = new RejectedPromise(null);
+ $this->assertTrue(P\is_rejected($p));
+ $this->assertFalse(P\is_fulfilled($p));
+ }
+
+ public function testKnowsIfSettled()
+ {
+ $p = new RejectedPromise(null);
+ $this->assertTrue(P\is_settled($p));
+ $p = new Promise();
+ $this->assertFalse(P\is_settled($p));
+ }
+
+ public function testReturnsTrampoline()
+ {
+ $this->assertInstanceOf('GuzzleHttp\Promise\TaskQueue', P\queue());
+ $this->assertSame(P\queue(), P\queue());
+ }
+
+ public function testCanScheduleThunk()
+ {
+ $tramp = P\queue();
+ $promise = P\task(function () { return 'Hi!'; });
+ $c = null;
+ $promise->then(function ($v) use (&$c) { $c = $v; });
+ $this->assertNull($c);
+ $tramp->run();
+ $this->assertEquals('Hi!', $c);
+ }
+
+ public function testCanScheduleThunkWithRejection()
+ {
+ $tramp = P\queue();
+ $promise = P\task(function () { throw new \Exception('Hi!'); });
+ $c = null;
+ $promise->otherwise(function ($v) use (&$c) { $c = $v; });
+ $this->assertNull($c);
+ $tramp->run();
+ $this->assertEquals('Hi!', $c->getMessage());
+ }
+
+ public function testCanScheduleThunkWithWait()
+ {
+ $tramp = P\queue();
+ $promise = P\task(function () { return 'a'; });
+ $this->assertEquals('a', $promise->wait());
+ $tramp->run();
+ }
+
+ public function testYieldsFromCoroutine()
+ {
+ $promise = P\coroutine(function () {
+ $value = (yield new P\FulfilledPromise('a'));
+ yield $value . 'b';
+ });
+ $promise->then(function ($value) use (&$result) { $result = $value; });
+ P\queue()->run();
+ $this->assertEquals('ab', $result);
+ }
+
+ public function testCanCatchExceptionsInCoroutine()
+ {
+ $promise = P\coroutine(function () {
+ try {
+ yield new P\RejectedPromise('a');
+ $this->fail('Should have thrown into the coroutine!');
+ } catch (P\RejectionException $e) {
+ $value = (yield new P\FulfilledPromise($e->getReason()));
+ yield $value . 'b';
+ }
+ });
+ $promise->then(function ($value) use (&$result) { $result = $value; });
+ P\queue()->run();
+ $this->assertEquals(P\PromiseInterface::FULFILLED, $promise->getState());
+ $this->assertEquals('ab', $result);
+ }
+
+ public function testRejectsParentExceptionWhenException()
+ {
+ $promise = P\coroutine(function () {
+ yield new P\FulfilledPromise(0);
+ throw new \Exception('a');
+ });
+ $promise->then(
+ function () { $this->fail(); },
+ function ($reason) use (&$result) { $result = $reason; }
+ );
+ P\queue()->run();
+ $this->assertInstanceOf('Exception', $result);
+ $this->assertEquals('a', $result->getMessage());
+ }
+
+ public function testCanRejectFromRejectionCallback()
+ {
+ $promise = P\coroutine(function () {
+ yield new P\FulfilledPromise(0);
+ yield new P\RejectedPromise('no!');
+ });
+ $promise->then(
+ function () { $this->fail(); },
+ function ($reason) use (&$result) { $result = $reason; }
+ );
+ P\queue()->run();
+ $this->assertInstanceOf('GuzzleHttp\Promise\RejectionException', $result);
+ $this->assertEquals('no!', $result->getReason());
+ }
+
+ public function testCanAsyncReject()
+ {
+ $rej = new P\Promise();
+ $promise = P\coroutine(function () use ($rej) {
+ yield new P\FulfilledPromise(0);
+ yield $rej;
+ });
+ $promise->then(
+ function () { $this->fail(); },
+ function ($reason) use (&$result) { $result = $reason; }
+ );
+ $rej->reject('no!');
+ P\queue()->run();
+ $this->assertInstanceOf('GuzzleHttp\Promise\RejectionException', $result);
+ $this->assertEquals('no!', $result->getReason());
+ }
+
+ public function testCanCatchAndThrowOtherException()
+ {
+ $promise = P\coroutine(function () {
+ try {
+ yield new P\RejectedPromise('a');
+ $this->fail('Should have thrown into the coroutine!');
+ } catch (P\RejectionException $e) {
+ throw new \Exception('foo');
+ }
+ });
+ $promise->otherwise(function ($value) use (&$result) { $result = $value; });
+ P\queue()->run();
+ $this->assertEquals(P\PromiseInterface::REJECTED, $promise->getState());
+ $this->assertContains('foo', $result->getMessage());
+ }
+
+ public function testCanCatchAndYieldOtherException()
+ {
+ $promise = P\coroutine(function () {
+ try {
+ yield new P\RejectedPromise('a');
+ $this->fail('Should have thrown into the coroutine!');
+ } catch (P\RejectionException $e) {
+ yield new P\RejectedPromise('foo');
+ }
+ });
+ $promise->otherwise(function ($value) use (&$result) { $result = $value; });
+ P\queue()->run();
+ $this->assertEquals(P\PromiseInterface::REJECTED, $promise->getState());
+ $this->assertContains('foo', $result->getMessage());
+ }
+
+ public function createLotsOfSynchronousPromise()
+ {
+ return P\coroutine(function () {
+ $value = 0;
+ for ($i = 0; $i < 1000; $i++) {
+ $value = (yield new P\FulfilledPromise($i));
+ }
+ yield $value;
+ });
+ }
+
+ public function testLotsOfSynchronousDoesNotBlowStack()
+ {
+ $promise = $this->createLotsOfSynchronousPromise();
+ $promise->then(function ($v) use (&$r) { $r = $v; });
+ P\queue()->run();
+ $this->assertEquals(999, $r);
+ }
+
+ public function testLotsOfSynchronousWaitDoesNotBlowStack()
+ {
+ $promise = $this->createLotsOfSynchronousPromise();
+ $promise->then(function ($v) use (&$r) { $r = $v; });
+ $this->assertEquals(999, $promise->wait());
+ $this->assertEquals(999, $r);
+ }
+
+ private function createLotsOfFlappingPromise()
+ {
+ return P\coroutine(function () {
+ $value = 0;
+ for ($i = 0; $i < 1000; $i++) {
+ try {
+ if ($i % 2) {
+ $value = (yield new P\FulfilledPromise($i));
+ } else {
+ $value = (yield new P\RejectedPromise($i));
+ }
+ } catch (\Exception $e) {
+ $value = (yield new P\FulfilledPromise($i));
+ }
+ }
+ yield $value;
+ });
+ }
+
+ public function testLotsOfTryCatchingDoesNotBlowStack()
+ {
+ $promise = $this->createLotsOfFlappingPromise();
+ $promise->then(function ($v) use (&$r) { $r = $v; });
+ P\queue()->run();
+ $this->assertEquals(999, $r);
+ }
+
+ public function testLotsOfTryCatchingWaitingDoesNotBlowStack()
+ {
+ $promise = $this->createLotsOfFlappingPromise();
+ $promise->then(function ($v) use (&$r) { $r = $v; });
+ $this->assertEquals(999, $promise->wait());
+ $this->assertEquals(999, $r);
+ }
+
+ public function testAsyncPromisesWithCorrectlyYieldedValues()
+ {
+ $promises = [
+ new P\Promise(),
+ new P\Promise(),
+ new P\Promise()
+ ];
+
+ $promise = P\coroutine(function () use ($promises) {
+ $value = null;
+ $this->assertEquals('skip', (yield new P\FulfilledPromise('skip')));
+ foreach ($promises as $idx => $p) {
+ $value = (yield $p);
+ $this->assertEquals($value, $idx);
+ $this->assertEquals('skip', (yield new P\FulfilledPromise('skip')));
+ }
+ $this->assertEquals('skip', (yield new P\FulfilledPromise('skip')));
+ yield $value;
+ });
+
+ $promises[0]->resolve(0);
+ $promises[1]->resolve(1);
+ $promises[2]->resolve(2);
+
+ $promise->then(function ($v) use (&$r) { $r = $v; });
+ P\queue()->run();
+ $this->assertEquals(2, $r);
+ }
+
+ public function testYieldFinalWaitablePromise()
+ {
+ $p1 = new P\Promise(function () use (&$p1) {
+ $p1->resolve('skip me');
+ });
+ $p2 = new P\Promise(function () use (&$p2) {
+ $p2->resolve('hello!');
+ });
+ $co = P\coroutine(function() use ($p1, $p2) {
+ yield $p1;
+ yield $p2;
+ });
+ P\queue()->run();
+ $this->assertEquals('hello!', $co->wait());
+ }
+
+ public function testCanYieldFinalPendingPromise()
+ {
+ $p1 = new P\Promise();
+ $p2 = new P\Promise();
+ $co = P\coroutine(function() use ($p1, $p2) {
+ yield $p1;
+ yield $p2;
+ });
+ $p1->resolve('a');
+ $p2->resolve('b');
+ $co->then(function ($value) use (&$result) { $result = $value; });
+ P\queue()->run();
+ $this->assertEquals('b', $result);
+ }
+
+ public function testCanNestYieldsAndFailures()
+ {
+ $p1 = new P\Promise();
+ $p2 = new P\Promise();
+ $p3 = new P\Promise();
+ $p4 = new P\Promise();
+ $p5 = new P\Promise();
+ $co = P\coroutine(function() use ($p1, $p2, $p3, $p4, $p5) {
+ try {
+ yield $p1;
+ } catch (\Exception $e) {
+ yield $p2;
+ try {
+ yield $p3;
+ yield $p4;
+ } catch (\Exception $e) {
+ yield $p5;
+ }
+ }
+ });
+ $p1->reject('a');
+ $p2->resolve('b');
+ $p3->resolve('c');
+ $p4->reject('d');
+ $p5->resolve('e');
+ $co->then(function ($value) use (&$result) { $result = $value; });
+ P\queue()->run();
+ $this->assertEquals('e', $result);
+ }
+
+ public function testCanYieldErrorsAndSuccessesWithoutRecursion()
+ {
+ $promises = [];
+ for ($i = 0; $i < 20; $i++) {
+ $promises[] = new P\Promise();
+ }
+
+ $co = P\coroutine(function() use ($promises) {
+ for ($i = 0; $i < 20; $i += 4) {
+ try {
+ yield $promises[$i];
+ yield $promises[$i + 1];
+ } catch (\Exception $e) {
+ yield $promises[$i + 2];
+ yield $promises[$i + 3];
+ }
+ }
+ });
+
+ for ($i = 0; $i < 20; $i += 4) {
+ $promises[$i]->resolve($i);
+ $promises[$i + 1]->reject($i + 1);
+ $promises[$i + 2]->resolve($i + 2);
+ $promises[$i + 3]->resolve($i + 3);
+ }
+
+ $co->then(function ($value) use (&$result) { $result = $value; });
+ P\queue()->run();
+ $this->assertEquals('19', $result);
+ }
+
+ public function testCanWaitOnPromiseAfterFulfilled()
+ {
+ $f = function () {
+ static $i = 0;
+ $i++;
+ return $p = new P\Promise(function () use (&$p, $i) {
+ $p->resolve($i . '-bar');
+ });
+ };
+
+ $promises = [];
+ for ($i = 0; $i < 20; $i++) {
+ $promises[] = $f();
+ }
+
+ $p = P\coroutine(function () use ($promises) {
+ yield new P\FulfilledPromise('foo!');
+ foreach ($promises as $promise) {
+ yield $promise;
+ }
+ });
+
+ $this->assertEquals('20-bar', $p->wait());
+ }
+
+ public function testCanWaitOnErroredPromises()
+ {
+ $p1 = new P\Promise(function () use (&$p1) { $p1->reject('a'); });
+ $p2 = new P\Promise(function () use (&$p2) { $p2->resolve('b'); });
+ $p3 = new P\Promise(function () use (&$p3) { $p3->resolve('c'); });
+ $p4 = new P\Promise(function () use (&$p4) { $p4->reject('d'); });
+ $p5 = new P\Promise(function () use (&$p5) { $p5->resolve('e'); });
+ $p6 = new P\Promise(function () use (&$p6) { $p6->reject('f'); });
+
+ $co = P\coroutine(function() use ($p1, $p2, $p3, $p4, $p5, $p6) {
+ try {
+ yield $p1;
+ } catch (\Exception $e) {
+ yield $p2;
+ try {
+ yield $p3;
+ yield $p4;
+ } catch (\Exception $e) {
+ yield $p5;
+ yield $p6;
+ }
+ }
+ });
+
+ $res = P\inspect($co);
+ $this->assertEquals('f', $res['reason']);
+ }
+
+ public function testCoroutineOtherwiseIntegrationTest()
+ {
+ $a = new P\Promise();
+ $b = new P\Promise();
+ $promise = P\coroutine(function () use ($a, $b) {
+ // Execute the pool of commands concurrently, and process errors.
+ yield $a;
+ yield $b;
+ })->otherwise(function (\Exception $e) {
+ // Throw errors from the operations as a specific Multipart error.
+ throw new \OutOfBoundsException('a', 0, $e);
+ });
+ $a->resolve('a');
+ $b->reject('b');
+ $reason = P\inspect($promise)['reason'];
+ $this->assertInstanceOf('OutOfBoundsException', $reason);
+ $this->assertInstanceOf('GuzzleHttp\Promise\RejectionException', $reason->getPrevious());
+ }
+}
diff --git a/server/vendor/guzzlehttp/psr7/.gitignore b/server/vendor/guzzlehttp/psr7/.gitignore
new file mode 100644
index 0000000..83ec41e
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/.gitignore
@@ -0,0 +1,11 @@
+phpunit.xml
+composer.phar
+composer.lock
+composer-test.lock
+vendor/
+build/artifacts/
+artifacts/
+docs/_build
+docs/*.pyc
+.idea
+.DS_STORE
diff --git a/server/vendor/guzzlehttp/psr7/.travis.yml b/server/vendor/guzzlehttp/psr7/.travis.yml
new file mode 100644
index 0000000..b88f8da
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/.travis.yml
@@ -0,0 +1,20 @@
+language: php
+
+php:
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+ - hhvm
+
+sudo: false
+
+install:
+ - travis_retry composer install --no-interaction --prefer-source
+
+script: make test
+
+matrix:
+ allow_failures:
+ - php: hhvm
+ fast_finish: true
diff --git a/server/vendor/guzzlehttp/psr7/CHANGELOG.md b/server/vendor/guzzlehttp/psr7/CHANGELOG.md
new file mode 100644
index 0000000..6cdfb39
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/CHANGELOG.md
@@ -0,0 +1,32 @@
+# CHANGELOG
+
+## 1.2.1 - 2015-11-02
+
+* Now supporting negative offsets when seeking to SEEK_END.
+
+## 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/server/vendor/guzzlehttp/psr7/LICENSE b/server/vendor/guzzlehttp/psr7/LICENSE
new file mode 100644
index 0000000..581d95f
--- /dev/null
+++ b/server/vendor/guzzlehttp/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/server/vendor/guzzlehttp/psr7/Makefile b/server/vendor/guzzlehttp/psr7/Makefile
new file mode 100644
index 0000000..9c21096
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/Makefile
@@ -0,0 +1,13 @@
+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/*
diff --git a/server/vendor/guzzlehttp/psr7/README.md b/server/vendor/guzzlehttp/psr7/README.md
new file mode 100644
index 0000000..0b30d5a
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/README.md
@@ -0,0 +1,580 @@
+# 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
+
+`GuzzleHttp\Psr7\AppendStream`
+
+Reads from multiple streams, one after the other.
+
+```php
+use GuzzleHttp\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
+
+`GuzzleHttp\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 GuzzleHttp\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 GuzzleHttp\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
+
+`GuzzleHttp\Psr7\DroppingStream`
+
+Stream decorator that begins dropping data once the size of the underlying
+stream becomes too full.
+
+```php
+use GuzzleHttp\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
+
+`GuzzleHttp\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 GuzzleHttp\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
+
+`GuzzleHttp\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
+
+`GuzzleHttp\Psr7\LazyOpenStream`
+
+Lazily reads or writes to a file that is opened only after an IO operation
+take place on the stream.
+
+```php
+use GuzzleHttp\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
+
+`GuzzleHttp\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 GuzzleHttp\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
+
+`GuzzleHttp\Psr7\MultipartStream`
+
+Stream that when read returns bytes for a streaming multipart or
+multipart/form-data stream.
+
+
+## NoSeekStream
+
+`GuzzleHttp\Psr7\NoSeekStream`
+
+NoSeekStream wraps a stream and does not allow seeking.
+
+```php
+use GuzzleHttp\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
+
+`GuzzleHttp\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
+`GuzzleHttp\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 GuzzleHttp\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 GuzzleHttp\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 `GuzzleHttp\Psr7\StreamWrapper` class if you need to use a
+PSR-7 stream as a PHP stream resource.
+
+Use the `GuzzleHttp\Psr7\StreamWrapper::getResource()` method to create a PHP
+stream from a PSR-7 stream.
+
+```php
+use GuzzleHttp\Psr7\StreamWrapper;
+
+$stream = GuzzleHttp\Psr7\stream_for('hello!');
+$resource = StreamWrapper::getResource($stream);
+echo fread($resource, 6); // outputs hello!
+```
+
+
+# Function API
+
+There are various functions available under the `GuzzleHttp\Psr7` namespace.
+
+
+## `function str`
+
+`function str(MessageInterface $message)`
+
+Returns the string representation of an HTTP message.
+
+```php
+$request = new GuzzleHttp\Psr7\Request('GET', 'http://example.com');
+echo GuzzleHttp\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 = GuzzleHttp\Psr7\uri_for('http://example.com');
+assert($uri === GuzzleHttp\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 = GuzzleHttp\Psr7\stream_for('foo');
+$stream = GuzzleHttp\Psr7\stream_for(fopen('/path/to/file', 'r'));
+
+$generator function ($bytes) {
+ for ($i = 0; $i < $bytes; $i++) {
+ yield ' ';
+ }
+}
+
+$stream = GuzzleHttp\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_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 `GuzzleHttp\Psr7\Uri` class has several static methods to manipulate URIs.
+
+
+## `GuzzleHttp\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
+
+
+## `GuzzleHttp\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
+
+
+## `GuzzleHttp\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".
+
+
+## `GuzzleHttp\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".
+
+
+## `GuzzleHttp\Psr7\Uri::fromParts`
+
+`public static function fromParts(array $parts) -> UriInterface`
+
+Create a `GuzzleHttp\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/server/vendor/guzzlehttp/psr7/composer.json b/server/vendor/guzzlehttp/psr7/composer.json
new file mode 100644
index 0000000..f2e9d4c
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/composer.json
@@ -0,0 +1,35 @@
+{
+ "name": "guzzlehttp/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.4.0",
+ "psr/http-message": "~1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "provide": {
+ "psr/http-message-implementation": "1.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Psr7\\": "src/"
+ },
+ "files": ["src/functions_include.php"]
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ }
+}
diff --git a/server/vendor/guzzlehttp/psr7/phpunit.xml.dist b/server/vendor/guzzlehttp/psr7/phpunit.xml.dist
new file mode 100644
index 0000000..500cd53
--- /dev/null
+++ b/server/vendor/guzzlehttp/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/server/vendor/guzzlehttp/psr7/src/AppendStream.php b/server/vendor/guzzlehttp/psr7/src/AppendStream.php
new file mode 100644
index 0000000..23039fd
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/AppendStream.php
@@ -0,0 +1,233 @@
+<?php
+namespace GuzzleHttp\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 = [];
+
+ 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 = [])
+ {
+ 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 = [];
+ }
+
+ /**
+ * 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 : [];
+ }
+}
diff --git a/server/vendor/guzzlehttp/psr7/src/BufferStream.php b/server/vendor/guzzlehttp/psr7/src/BufferStream.php
new file mode 100644
index 0000000..af4d4c2
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/BufferStream.php
@@ -0,0 +1,137 @@
+<?php
+namespace GuzzleHttp\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 : [];
+ }
+}
diff --git a/server/vendor/guzzlehttp/psr7/src/CachingStream.php b/server/vendor/guzzlehttp/psr7/src/CachingStream.php
new file mode 100644
index 0000000..420d5b0
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/CachingStream.php
@@ -0,0 +1,135 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Stream decorator that can cache previously read bytes from a sequentially
+ * read stream.
+ */
+class CachingStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ /** @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;
+ $this->stream = $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();
+ }
+ $byte = $size + $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(['write' => 'strlen']);
+ copy_to_stream($this, $target);
+
+ return $this->tell();
+ }
+}
diff --git a/server/vendor/guzzlehttp/psr7/src/DroppingStream.php b/server/vendor/guzzlehttp/psr7/src/DroppingStream.php
new file mode 100644
index 0000000..8935c80
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/DroppingStream.php
@@ -0,0 +1,42 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Stream decorator that begins dropping data once the size of the underlying
+ * stream becomes too full.
+ */
+class DroppingStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ private $maxLength;
+
+ /**
+ * @param StreamInterface $stream Underlying stream to decorate.
+ * @param int $maxLength Maximum size before dropping data.
+ */
+ public function __construct(StreamInterface $stream, $maxLength)
+ {
+ $this->stream = $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/server/vendor/guzzlehttp/psr7/src/FnStream.php b/server/vendor/guzzlehttp/psr7/src/FnStream.php
new file mode 100644
index 0000000..cc9b445
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/FnStream.php
@@ -0,0 +1,149 @@
+<?php
+namespace GuzzleHttp\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.
+ */
+class FnStream implements StreamInterface
+{
+ /** @var array */
+ private $methods;
+
+ /** @var array Methods that must be implemented in the given array */
+ private static $slots = ['__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] = [$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/server/vendor/guzzlehttp/psr7/src/InflateStream.php b/server/vendor/guzzlehttp/psr7/src/InflateStream.php
new file mode 100644
index 0000000..2c8628b
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/InflateStream.php
@@ -0,0 +1,29 @@
+<?php
+namespace GuzzleHttp\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 implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ 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);
+ $this->stream = new Stream($resource);
+ }
+}
diff --git a/server/vendor/guzzlehttp/psr7/src/LazyOpenStream.php b/server/vendor/guzzlehttp/psr7/src/LazyOpenStream.php
new file mode 100644
index 0000000..02cec3a
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/LazyOpenStream.php
@@ -0,0 +1,39 @@
+<?php
+namespace GuzzleHttp\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 implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ /** @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;
+ }
+
+ /**
+ * Creates the underlying stream lazily when required.
+ *
+ * @return StreamInterface
+ */
+ protected function createStream()
+ {
+ return stream_for(try_fopen($this->filename, $this->mode));
+ }
+}
diff --git a/server/vendor/guzzlehttp/psr7/src/LimitStream.php b/server/vendor/guzzlehttp/psr7/src/LimitStream.php
new file mode 100644
index 0000000..7f2298b
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/LimitStream.php
@@ -0,0 +1,155 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+
+/**
+ * Decorator used to return only a subset of a stream
+ */
+class LimitStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ /** @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
+ ) {
+ $this->stream = $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/server/vendor/guzzlehttp/psr7/src/MessageTrait.php b/server/vendor/guzzlehttp/psr7/src/MessageTrait.php
new file mode 100644
index 0000000..123205c
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/MessageTrait.php
@@ -0,0 +1,158 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Trait implementing functionality common to requests and responses.
+ */
+trait MessageTrait
+{
+ /** @var array Cached HTTP header collection with lowercase key to values */
+ private $headers = [];
+
+ /** @var array Actual key to list of values per header. */
+ private $headerLines = [];
+
+ /** @var string */
+ private $protocol = '1.1';
+
+ /** @var StreamInterface */
+ private $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] : [];
+ }
+
+ 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] = [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);
+ }
+
+ $new = clone $this;
+ $new->headers[strtolower($header)][] = $value;
+ $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;
+ }
+
+ private function setHeaders(array $headers)
+ {
+ $this->headerLines = $this->headers = [];
+ 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/server/vendor/guzzlehttp/psr7/src/MultipartStream.php b/server/vendor/guzzlehttp/psr7/src/MultipartStream.php
new file mode 100644
index 0000000..fd006ec
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/MultipartStream.php
@@ -0,0 +1,153 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Stream that when read returns bytes for a streaming multipart or
+ * multipart/form-data stream.
+ */
+class MultipartStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ 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 = [], $boundary = null)
+ {
+ $this->boundary = $boundary ?: uniqid();
+ $this->stream = $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 (['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'] : []
+ );
+
+ $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 [$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/server/vendor/guzzlehttp/psr7/src/NoSeekStream.php b/server/vendor/guzzlehttp/psr7/src/NoSeekStream.php
new file mode 100644
index 0000000..2332218
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/NoSeekStream.php
@@ -0,0 +1,22 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Stream decorator that prevents a stream from being seeked
+ */
+class NoSeekStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ throw new \RuntimeException('Cannot seek a NoSeekStream');
+ }
+
+ public function isSeekable()
+ {
+ return false;
+ }
+}
diff --git a/server/vendor/guzzlehttp/psr7/src/PumpStream.php b/server/vendor/guzzlehttp/psr7/src/PumpStream.php
new file mode 100644
index 0000000..ffb5440
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/PumpStream.php
@@ -0,0 +1,165 @@
+<?php
+namespace GuzzleHttp\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(callable $source, array $options = [])
+ {
+ $this->source = $source;
+ $this->size = isset($options['size']) ? $options['size'] : null;
+ $this->metadata = isset($options['metadata']) ? $options['metadata'] : [];
+ $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/server/vendor/guzzlehttp/psr7/src/Request.php b/server/vendor/guzzlehttp/psr7/src/Request.php
new file mode 100644
index 0000000..ed1d3f5
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/Request.php
@@ -0,0 +1,149 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use InvalidArgumentException;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\StreamInterface;
+use Psr\Http\Message\UriInterface;
+
+/**
+ * PSR-7 request implementation.
+ */
+class Request implements RequestInterface
+{
+ use MessageTrait {
+ withHeader as protected withParentHeader;
+ }
+
+ /** @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 = [],
+ $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 = $this->withParentHeader($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 = ['Host' => [$host]] + $this->headerLines;
+ $this->headers = ['host' => [$host]] + $this->headers;
+ }
+}
diff --git a/server/vendor/guzzlehttp/psr7/src/Response.php b/server/vendor/guzzlehttp/psr7/src/Response.php
new file mode 100644
index 0000000..c94bf8f
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/Response.php
@@ -0,0 +1,130 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * PSR-7 response implementation.
+ */
+class Response implements ResponseInterface
+{
+ use MessageTrait;
+
+ /** @var array Map of standard HTTP status code/reason phrases */
+ private static $phrases = [
+ 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 = [],
+ $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/server/vendor/guzzlehttp/psr7/src/Stream.php b/server/vendor/guzzlehttp/psr7/src/Stream.php
new file mode 100644
index 0000000..0b0db01
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/Stream.php
@@ -0,0 +1,245 @@
+<?php
+namespace GuzzleHttp\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 = [
+ 'read' => [
+ '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' => [
+ '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 = [])
+ {
+ 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']
+ : [];
+
+ $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 : [];
+ } 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/server/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php b/server/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php
new file mode 100644
index 0000000..daec6f5
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php
@@ -0,0 +1,149 @@
+<?php
+namespace GuzzleHttp\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Stream decorator trait
+ * @property StreamInterface stream
+ */
+trait StreamDecoratorTrait
+{
+ /**
+ * @param StreamInterface $stream Stream to decorate
+ */
+ public function __construct(StreamInterface $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([$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);
+ }
+
+ /**
+ * Implement in subclasses to dynamically create streams when requested.
+ *
+ * @return StreamInterface
+ * @throws \BadMethodCallException
+ */
+ protected function createStream()
+ {
+ throw new \BadMethodCallException('Not implemented');
+ }
+}
diff --git a/server/vendor/guzzlehttp/psr7/src/StreamWrapper.php b/server/vendor/guzzlehttp/psr7/src/StreamWrapper.php
new file mode 100644
index 0000000..cf7b223
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/StreamWrapper.php
@@ -0,0 +1,121 @@
+<?php
+namespace GuzzleHttp\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([
+ 'guzzle' => ['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 = [
+ 'r' => 33060,
+ 'r+' => 33206,
+ 'w' => 33188
+ ];
+
+ return [
+ '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/server/vendor/guzzlehttp/psr7/src/Uri.php b/server/vendor/guzzlehttp/psr7/src/Uri.php
new file mode 100644
index 0000000..d428f2e
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/Uri.php
@@ -0,0 +1,599 @@
+<?php
+namespace GuzzleHttp\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 = [
+ 'http' => 80,
+ 'https' => 443,
+ ];
+
+ private static $charUnreserved = 'a-zA-Z0-9_\-\.~';
+ private static $charSubDelims = '!\$&\'\(\)\*\+,;=';
+ private static $replaceQuery = ['=' => '%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 = ['' => true, '/' => true, '*' => true];
+ static $ignoreSegments = ['.' => true, '..' => true];
+
+ if (isset($noopPaths[$path])) {
+ return $path;
+ }
+
+ $results = [];
+ $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 = [
+ 'scheme' => $rel->getScheme(),
+ 'authority' => $rel->getAuthority(),
+ 'path' => $rel->getPath(),
+ 'query' => $rel->getQuery(),
+ 'fragment' => $rel->getFragment()
+ ];
+
+ $parts = [
+ '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 = [];
+ foreach (explode('&', $current) as $part) {
+ if (explode('=', $part)[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 = [];
+ } else {
+ $result = [];
+ foreach (explode('&', $current) as $part) {
+ if (explode('=', $part)[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}))/',
+ [$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}))/',
+ [$this, 'rawurlencodeMatchZero'],
+ $str
+ );
+ }
+
+ private function rawurlencodeMatchZero(array $match)
+ {
+ return rawurlencode($match[0]);
+ }
+}
diff --git a/server/vendor/guzzlehttp/psr7/src/functions.php b/server/vendor/guzzlehttp/psr7/src/functions.php
new file mode 100644
index 0000000..fd3e7f5
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/functions.php
@@ -0,0 +1,802 @@
+<?php
+namespace GuzzleHttp\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;
+
+/**
+ * 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 = [])
+{
+ 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 = [];
+
+ foreach (normalize_header($header) as $val) {
+ $part = [];
+ 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 = [];
+ 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;
+ set_error_handler(function () use ($filename, $mode, &$ex) {
+ $ex = new \RuntimeException(sprintf(
+ 'Unable to open %s using mode %s: %s',
+ $filename,
+ $mode,
+ func_get_args()[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 = [];
+ 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);
+ $version = isset($parts[2]) ? explode('/', $parts[2])[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 response message string into a response object.
+ *
+ * @param string $message Response message string.
+ *
+ * @return Response
+ */
+function parse_response($message)
+{
+ $data = _parse_message($message);
+ if (!preg_match('/^HTTP\/.* [0-9]{3} .*/', $data['start-line'])) {
+ throw new \InvalidArgumentException('Invalid response string');
+ }
+ $parts = explode(' ', $data['start-line'], 3);
+
+ return new Response(
+ $parts[1],
+ $data['headers'],
+ $data['body'],
+ explode('/', $parts[0])[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 = [];
+
+ 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] = [$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 = [
+ '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 = ['start-line' => array_shift($lines), 'headers' => [], '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 = [];
+
+ 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/server/vendor/guzzlehttp/psr7/src/functions_include.php b/server/vendor/guzzlehttp/psr7/src/functions_include.php
new file mode 100644
index 0000000..96a4a83
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/src/functions_include.php
@@ -0,0 +1,6 @@
+<?php
+
+// Don't redefine the functions if included multiple times.
+if (!function_exists('GuzzleHttp\Psr7\str')) {
+ require __DIR__ . '/functions.php';
+}
diff --git a/server/vendor/guzzlehttp/psr7/tests/AppendStreamTest.php b/server/vendor/guzzlehttp/psr7/tests/AppendStreamTest.php
new file mode 100644
index 0000000..3c197dc
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/tests/AppendStreamTest.php
@@ -0,0 +1,186 @@
+<?php
+namespace GuzzleHttp\Tests\Psr7;
+
+use GuzzleHttp\Psr7\AppendStream;
+use GuzzleHttp\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(['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(['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([
+ 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([$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([$s1]);
+ $a->close();
+ $this->assertSame('', (string) $a);
+ }
+
+ /**
+ * @expectedExceptionMessage Cannot write to an AppendStream
+ * @expectedException \RuntimeException
+ */
+ public function testIsNotWritable()
+ {
+ $a = new AppendStream([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([
+ 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([
+ Psr7\stream_for('foo'),
+ Psr7\stream_for('bar')
+ ]);
+ $this->assertEquals(6, $a->getSize());
+
+ $s = $this->getMockBuilder('Psr\Http\Message\StreamInterface')
+ ->setMethods(['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(['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([$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([], $s->getMetadata());
+ $this->assertNull($s->getMetadata('foo'));
+ }
+}
diff --git a/server/vendor/guzzlehttp/psr7/tests/BufferStreamTest.php b/server/vendor/guzzlehttp/psr7/tests/BufferStreamTest.php
new file mode 100644
index 0000000..0a635d4
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/tests/BufferStreamTest.php
@@ -0,0 +1,63 @@
+<?php
+namespace GuzzleHttp\Tests\Psr7;
+
+use GuzzleHttp\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([], $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/server/vendor/guzzlehttp/psr7/tests/CachingStreamTest.php b/server/vendor/guzzlehttp/psr7/tests/CachingStreamTest.php
new file mode 100644
index 0000000..326f754
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/tests/CachingStreamTest.php
@@ -0,0 +1,166 @@
+<?php
+namespace GuzzleHttp\Tests\Psr7;
+
+use GuzzleHttp\Psr7;
+use GuzzleHttp\Psr7\CachingStream;
+
+/**
+ * @covers GuzzleHttp\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(25, $baseStream->tell());
+ $this->assertEquals('z', $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(26, $baseStream->tell());
+ $this->assertEquals('', $cached->read(1));
+ $this->assertEquals(26, $cached->getSize());
+ }
+
+ public function testCanUseSeekEndWithUnknownSize()
+ {
+ $baseStream = Psr7\stream_for('testing');
+ $decorated = Psr7\FnStream::decorate($baseStream, [
+ 'getSize' => function () { return null; }
+ ]);
+ $cached = new CachingStream($decorated);
+ $cached->seek(-1, SEEK_END);
+ $this->assertEquals('g', $cached->read(1));
+ }
+
+ public function testRewindUsesSeek()
+ {
+ $a = Psr7\stream_for('foo');
+ $d = $this->getMockBuilder('GuzzleHttp\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/server/vendor/guzzlehttp/psr7/tests/DroppingStreamTest.php b/server/vendor/guzzlehttp/psr7/tests/DroppingStreamTest.php
new file mode 100644
index 0000000..915b215
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/tests/DroppingStreamTest.php
@@ -0,0 +1,26 @@
+<?php
+namespace GuzzleHttp\Tests\Psr7;
+
+use GuzzleHttp\Psr7\BufferStream;
+use GuzzleHttp\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/server/vendor/guzzlehttp/psr7/tests/FnStreamTest.php b/server/vendor/guzzlehttp/psr7/tests/FnStreamTest.php
new file mode 100644
index 0000000..66ae90a
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/tests/FnStreamTest.php
@@ -0,0 +1,90 @@
+<?php
+namespace GuzzleHttp\Tests\Psr7;
+
+use GuzzleHttp\Psr7;
+use GuzzleHttp\Psr7\FnStream;
+
+/**
+ * @covers GuzzleHttp\Psr7\FnStream
+ */
+class FnStreamTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException \BadMethodCallException
+ * @expectedExceptionMessage seek() is not implemented in the FnStream
+ */
+ public function testThrowsWhenNotImplemented()
+ {
+ (new FnStream([]))->seek(1);
+ }
+
+ public function testProxiesToFunction()
+ {
+ $s = new FnStream([
+ 'read' => function ($len) {
+ $this->assertEquals(3, $len);
+ return 'foo';
+ }
+ ]);
+
+ $this->assertEquals('foo', $s->read(3));
+ }
+
+ public function testCanCloseOnDestruct()
+ {
+ $called = false;
+ $s = new FnStream([
+ 'close' => function () use (&$called) {
+ $called = true;
+ }
+ ]);
+ unset($s);
+ $this->assertTrue($called);
+ }
+
+ public function testDoesNotRequireClose()
+ {
+ $s = new FnStream([]);
+ unset($s);
+ }
+
+ public function testDecoratesStream()
+ {
+ $a = Psr7\stream_for('foo');
+ $b = FnStream::decorate($a, []);
+ $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, [
+ 'read' => function ($len) use (&$called, $a) {
+ $called = true;
+ return $a->read($len);
+ }
+ ]);
+ $this->assertEquals('foo', $b->read(3));
+ $this->assertTrue($called);
+ }
+}
diff --git a/server/vendor/guzzlehttp/psr7/tests/FunctionsTest.php b/server/vendor/guzzlehttp/psr7/tests/FunctionsTest.php
new file mode 100644
index 0000000..de5b5cb
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/tests/FunctionsTest.php
@@ -0,0 +1,586 @@
+<?php
+namespace GuzzleHttp\Tests\Psr7;
+
+use GuzzleHttp\Psr7;
+use GuzzleHttp\Psr7\FnStream;
+use GuzzleHttp\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, [
+ '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, ['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, ['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, ['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('GuzzleHttp\Psr7\Stream')
+ ->setMethods(['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 [
+ // Does not need to parse when the string is empty
+ ['', []],
+ // Can parse mult-values items
+ ['q=a&q=b', ['q' => ['a', 'b']]],
+ // Can parse multi-valued items that use numeric indices
+ ['q[0]=a&q[1]=b', ['q[0]' => 'a', 'q[1]' => 'b']],
+ // Can parse duplicates and does not include numeric indices
+ ['q[]=a&q[]=b', ['q[]' => ['a', 'b']]],
+ // Ensures that the value of "q" is an array even though one value
+ ['q[]=a', ['q[]' => 'a']],
+ // Does not modify "." to "_" like PHP's parse_str()
+ ['q.a=a&q.b=b', ['q.a' => 'a', 'q.b' => 'b']],
+ // Can decode %20 to " "
+ ['q%20a=a%20b', ['q a' => 'a b']],
+ // Can parse funky strings with no values by assigning each to null
+ ['q&a', ['q' => null, 'a' => null]],
+ // Does not strip trailing equal signs
+ ['data=abc=', ['data' => 'abc=']],
+ // Can store duplicates without affecting other values
+ ['foo=a&foo=b&?µ=c', ['foo' => ['a', 'b'], '?µ' => 'c']],
+ // Sets value to null when no "=" is present
+ ['foo', ['foo' => null]],
+ // Preserves "0" keys.
+ ['0', ['0' => null]],
+ // Sets the value to an empty string when "=" is present
+ ['0=', ['0' => '']],
+ // Preserves falsey keys
+ ['var=0', ['var' => '0']],
+ ['a[b][c]=1&a[b][c]=2', ['a[b][c]' => ['1', '2']]],
+ ['a[b]=c&a[d]=e', ['a[b]' => 'c', 'a[d]' => 'e']],
+ // Ensure it doesn't leave things behind with repeated values
+ // Can parse mult-values items
+ ['q=a&q=b&q=c', ['q' => ['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(['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(['foo bar' => 'baz+'], PHP_QUERY_RFC1738);
+ $this->assertEquals('foo+bar=baz%2B', $str);
+ }
+
+ public function testEncodesWithRfc3986()
+ {
+ $str = Psr7\build_query(['foo bar' => 'baz+'], PHP_QUERY_RFC3986);
+ $this->assertEquals('foo%20bar=baz%2B', $str);
+ }
+
+ public function testDoesNotEncode()
+ {
+ $str = Psr7\build_query(['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('GuzzleHttp\Psr7\Uri', Psr7\uri_for('/foo'));
+ $this->assertInstanceOf(
+ 'GuzzleHttp\Psr7\Uri',
+ Psr7\uri_for(new Psr7\Uri('/foo'))
+ );
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testValidatesUri()
+ {
+ Psr7\uri_for([]);
+ }
+
+ 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('GuzzleHttp\Psr7\Stream', $stream);
+ $this->assertEquals('foo', $stream->getContents());
+ $stream->close();
+ }
+
+ public function testFactoryCreatesFromEmptyString()
+ {
+ $s = Psr7\stream_for();
+ $this->assertInstanceOf('GuzzleHttp\Psr7\Stream', $s);
+ }
+
+ public function testFactoryCreatesFromNull()
+ {
+ $s = Psr7\stream_for(null);
+ $this->assertInstanceOf('GuzzleHttp\Psr7\Stream', $s);
+ }
+
+ public function testFactoryCreatesFromResource()
+ {
+ $r = fopen(__FILE__, 'r');
+ $s = Psr7\stream_for($r);
+ $this->assertInstanceOf('GuzzleHttp\Psr7\Stream', $s);
+ $this->assertSame(file_get_contents(__FILE__), (string) $s);
+ }
+
+ public function testFactoryCreatesFromObjectWithToString()
+ {
+ $r = new HasToString();
+ $s = Psr7\stream_for($r);
+ $this->assertInstanceOf('GuzzleHttp\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', ['metadata' => ['hwm' => 3]]);
+ $this->assertEquals(3, $s->getMetadata('hwm'));
+ $this->assertArrayHasKey('hwm', $s->getMetadata());
+ }
+
+ public function testCanSetSize()
+ {
+ $s = Psr7\stream_for('', ['size' => 10]);
+ $this->assertEquals(10, $s->getSize());
+ }
+
+ public function testCanCreateIteratorBasedStream()
+ {
+ $a = new \ArrayIterator(['foo', 'bar', '123']);
+ $p = Psr7\stream_for($a);
+ $this->assertInstanceOf('GuzzleHttp\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', [
+ '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, [
+ '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 = ['a, b', 'c', 'd, e'];
+ $this->assertEquals(['a', 'b', 'c', 'd', 'e'], Psr7\normalize_header($header));
+ }
+
+ public function testRewindsBody()
+ {
+ $body = Psr7\stream_for('abc');
+ $res = new Psr7\Response(200, [], $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, [
+ 'rewind' => function () { throw new \RuntimeException('a'); }
+ ]);
+ $res = new Psr7\Response(200, [], $body);
+ Psr7\rewind_body($res);
+ }
+
+ public function testCanModifyRequestWithUri()
+ {
+ $r1 = new Psr7\Request('GET', 'http://foo.com');
+ $r2 = Psr7\modify_request($r1, [
+ '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', ['User-Agent' => 'foo']);
+ $r2 = Psr7\modify_request($r1, ['set_headers' => ['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, []));
+ }
+
+ public function testReturnsUriAsIsWhenNoChanges()
+ {
+ $r1 = new Psr7\Request('GET', 'http://foo.com');
+ $r2 = Psr7\modify_request($r1, ['set_headers' => ['foo' => 'bar']]);
+ $this->assertNotSame($r1, $r2);
+ $this->assertEquals('bar', $r2->getHeaderLine('foo'));
+ }
+
+ public function testRemovesHeadersFromMessage()
+ {
+ $r1 = new Psr7\Request('GET', 'http://foo.com', ['foo' => 'bar']);
+ $r2 = Psr7\modify_request($r1, ['remove_headers' => ['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, ['query' => 'foo=bar']);
+ $this->assertNotSame($r1, $r2);
+ $this->assertEquals('foo=bar', $r2->getUri()->getQuery());
+ }
+}
diff --git a/server/vendor/guzzlehttp/psr7/tests/InflateStreamTest.php b/server/vendor/guzzlehttp/psr7/tests/InflateStreamTest.php
new file mode 100644
index 0000000..927fc0b
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/tests/InflateStreamTest.php
@@ -0,0 +1,16 @@
+<?php
+namespace GuzzleHttp\Tests\Psr7;
+
+use GuzzleHttp\Psr7;
+use GuzzleHttp\Psr7\InflateStream;
+
+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/server/vendor/guzzlehttp/psr7/tests/LazyOpenStreamTest.php b/server/vendor/guzzlehttp/psr7/tests/LazyOpenStreamTest.php
new file mode 100644
index 0000000..fdef142
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/tests/LazyOpenStreamTest.php
@@ -0,0 +1,64 @@
+<?php
+namespace GuzzleHttp\Tests\Psr7;
+
+use GuzzleHttp\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/server/vendor/guzzlehttp/psr7/tests/LimitStreamTest.php b/server/vendor/guzzlehttp/psr7/tests/LimitStreamTest.php
new file mode 100644
index 0000000..2198b7a
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/tests/LimitStreamTest.php
@@ -0,0 +1,166 @@
+<?php
+namespace GuzzleHttp\Tests\Psr7;
+
+use GuzzleHttp\Psr7;
+use GuzzleHttp\Psr7\FnStream;
+use GuzzleHttp\Psr7\Stream;
+use GuzzleHttp\Psr7\LimitStream;
+use GuzzleHttp\Psr7\NoSeekStream;
+
+/**
+ * @covers GuzzleHttp\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([
+ '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/server/vendor/guzzlehttp/psr7/tests/MultipartStreamTest.php b/server/vendor/guzzlehttp/psr7/tests/MultipartStreamTest.php
new file mode 100644
index 0000000..61edb06
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/tests/MultipartStreamTest.php
@@ -0,0 +1,214 @@
+<?php
+namespace GuzzleHttp\Tests;
+
+use GuzzleHttp\Psr7;
+use GuzzleHttp\Psr7\MultipartStream;
+
+class MultipartStreamTest extends \PHPUnit_Framework_TestCase
+{
+ public function testCreatesDefaultBoundary()
+ {
+ $b = new MultipartStream();
+ $this->assertNotEmpty($b->getBoundary());
+ }
+
+ public function testCanProvideBoundary()
+ {
+ $b = new MultipartStream([], '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([['foo' => 'bar']]);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testEnsuresFileHasName()
+ {
+ new MultipartStream([['contents' => 'bar']]);
+ }
+
+ public function testSerializesFields()
+ {
+ $b = new MultipartStream([
+ [
+ 'name' => 'foo',
+ 'contents' => 'bar'
+ ],
+ [
+ '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'), [
+ 'getMetadata' => function () {
+ return '/foo/bar.txt';
+ }
+ ]);
+
+ $f2 = Psr7\FnStream::decorate(Psr7\stream_for('baz'), [
+ 'getMetadata' => function () {
+ return '/foo/baz.jpg';
+ }
+ ]);
+
+ $f3 = Psr7\FnStream::decorate(Psr7\stream_for('bar'), [
+ 'getMetadata' => function () {
+ return '/foo/bar.gif';
+ }
+ ]);
+
+ $b = new MultipartStream([
+ [
+ 'name' => 'foo',
+ 'contents' => $f1
+ ],
+ [
+ 'name' => 'qux',
+ 'contents' => $f2
+ ],
+ [
+ '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'), [
+ 'getMetadata' => function () {
+ return '/foo/bar.txt';
+ }
+ ]);
+
+ $b = new MultipartStream([
+ [
+ 'name' => 'foo',
+ 'contents' => $f1,
+ 'headers' => [
+ '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'), [
+ 'getMetadata' => function () {
+ return '/foo/bar.txt';
+ }
+ ]);
+
+ $f2 = Psr7\FnStream::decorate(Psr7\stream_for('baz'), [
+ 'getMetadata' => function () {
+ return '/foo/baz.jpg';
+ }
+ ]);
+
+ $b = new MultipartStream([
+ [
+ 'name' => 'foo',
+ 'contents' => $f1,
+ 'headers' => [
+ 'x-foo' => 'bar',
+ 'content-disposition' => 'custom'
+ ]
+ ],
+ [
+ 'name' => 'foo',
+ 'contents' => $f2,
+ 'headers' => ['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/server/vendor/guzzlehttp/psr7/tests/NoSeekStreamTest.php b/server/vendor/guzzlehttp/psr7/tests/NoSeekStreamTest.php
new file mode 100644
index 0000000..a309317
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/tests/NoSeekStreamTest.php
@@ -0,0 +1,40 @@
+<?php
+namespace GuzzleHttp\Tests\Psr7;
+
+use GuzzleHttp\Psr7;
+use GuzzleHttp\Psr7\NoSeekStream;
+
+/**
+ * @covers GuzzleHttp\Psr7\NoSeekStream
+ * @covers GuzzleHttp\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(['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/server/vendor/guzzlehttp/psr7/tests/PumpStreamTest.php b/server/vendor/guzzlehttp/psr7/tests/PumpStreamTest.php
new file mode 100644
index 0000000..7358bb6
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/tests/PumpStreamTest.php
@@ -0,0 +1,72 @@
+<?php
+namespace GuzzleHttp\Tests\Psr7;
+
+use GuzzleHttp\Psr7\LimitStream;
+use GuzzleHttp\Psr7\PumpStream;
+use GuzzleHttp\Psr7;
+
+class PumpStreamTest extends \PHPUnit_Framework_TestCase
+{
+ public function testHasMetadataAndSize()
+ {
+ $p = new PumpStream(function () {}, [
+ 'metadata' => ['foo' => 'bar'],
+ 'size' => 100
+ ]);
+
+ $this->assertEquals('bar', $p->getMetadata('foo'));
+ $this->assertEquals(['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 = [];
+ $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([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/server/vendor/guzzlehttp/psr7/tests/RequestTest.php b/server/vendor/guzzlehttp/psr7/tests/RequestTest.php
new file mode 100644
index 0000000..9defe68
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/tests/RequestTest.php
@@ -0,0 +1,157 @@
+<?php
+namespace GuzzleHttp\Tests\Psr7;
+
+use GuzzleHttp\Psr7\Request;
+use GuzzleHttp\Psr7\Uri;
+
+/**
+ * @covers GuzzleHttp\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', '/', [], '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', ['Foo' => 'Bar']);
+ $this->assertEquals([
+ 'Host' => ['foo.com'],
+ 'Foo' => ['Bar']
+ ], $r->getHeaders());
+ }
+
+ public function testCanGetHeaderAsCsv()
+ {
+ $r = new Request('GET', 'http://foo.com/baz?bar=bam', [
+ 'Foo' => ['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', ['Host' => 'a.com']);
+ $this->assertEquals(['Host' => ['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(['Host' => ['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', [
+ 'ZOO' => 'zoobar',
+ 'zoo' => ['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/server/vendor/guzzlehttp/psr7/tests/ResponseTest.php b/server/vendor/guzzlehttp/psr7/tests/ResponseTest.php
new file mode 100644
index 0000000..0ce3e21
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/tests/ResponseTest.php
@@ -0,0 +1,146 @@
+<?php
+namespace GuzzleHttp\Tests\Psr7;
+
+use GuzzleHttp\Psr7\Response;
+use GuzzleHttp\Psr7;
+
+/**
+ * @covers GuzzleHttp\Psr7\MessageTrait
+ * @covers GuzzleHttp\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, [], null, '1.1', 'bar');
+ $this->assertEquals('bar', $r->getReasonPhrase());
+ }
+
+ public function testCanGiveCustomProtocolVersion()
+ {
+ $r = new Response(200, [], 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', ['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, [
+ 'foo' => ['baz ', ' bar ']
+ ]);
+ $this->assertEquals('baz, bar', $r->getHeaderLine('foo'));
+ $this->assertEquals(['baz', 'bar'], $r->getHeader('foo'));
+ }
+
+ public function testSameInstanceWhenSameBody()
+ {
+ $r = new Response(200, [], 'foo');
+ $b = $r->getBody();
+ $this->assertSame($r, $r->withBody($b));
+ }
+
+ public function testNewInstanceWhenNewBody()
+ {
+ $r = new Response(200, [], '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, ['Foo' => 'Bar']);
+ $r2 = $r->withoutHeader('Foo');
+ $this->assertNotSame($r, $r2);
+ $this->assertFalse($r2->hasHeader('foo'));
+ }
+
+ public function testNewInstanceWhenAddingHeader()
+ {
+ $r = new Response(200, ['Foo' => 'Bar']);
+ $r2 = $r->withAddedHeader('Foo', 'Baz');
+ $this->assertNotSame($r, $r2);
+ $this->assertEquals('Bar, Baz', $r2->getHeaderLine('foo'));
+ }
+
+ public function testNewInstanceWhenAddingHeaderThatWasNotThereBefore()
+ {
+ $r = new Response(200, ['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, ['Foo' => 'Bar']);
+ $r2 = $r->withHeader('foo', 'Bam');
+ $this->assertNotSame($r, $r2);
+ $this->assertEquals('Bam', $r2->getHeaderLine('Foo'));
+ }
+
+ public function testBodyConsistent()
+ {
+ $r = new Response(200, [], '0');
+ $this->assertEquals('0', (string)$r->getBody());
+ }
+
+}
diff --git a/server/vendor/guzzlehttp/psr7/tests/StreamDecoratorTraitTest.php b/server/vendor/guzzlehttp/psr7/tests/StreamDecoratorTraitTest.php
new file mode 100644
index 0000000..682079e
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/tests/StreamDecoratorTraitTest.php
@@ -0,0 +1,137 @@
+<?php
+namespace GuzzleHttp\Tests\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+use GuzzleHttp\Psr7;
+use GuzzleHttp\Psr7\StreamDecoratorTrait;
+
+class Str implements StreamInterface
+{
+ use StreamDecoratorTrait;
+}
+
+/**
+ * @covers GuzzleHttp\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(['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;
+ }
+
+ /**
+ * @expectedException \BadMethodCallException
+ */
+ public function testThrowsWhenGetterNotImplemented()
+ {
+ $s = new BadStream();
+ $s->stream;
+ }
+}
+
+class BadStream
+{
+ use StreamDecoratorTrait;
+
+ public function __construct() {}
+}
diff --git a/server/vendor/guzzlehttp/psr7/tests/StreamTest.php b/server/vendor/guzzlehttp/psr7/tests/StreamTest.php
new file mode 100644
index 0000000..4fe92cc
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/tests/StreamTest.php
@@ -0,0 +1,161 @@
+<?php
+namespace GuzzleHttp\Tests\Psr7;
+
+use GuzzleHttp\Psr7\NoSeekStream;
+use GuzzleHttp\Psr7\Stream;
+
+/**
+ * @covers GuzzleHttp\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());
+
+ $throws = function (callable $fn) use ($stream) {
+ try {
+ $fn($stream);
+ $this->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 = \GuzzleHttp\Psr7\stream_for('foo');
+ $s = new NoSeekStream($s);
+ $this->assertEquals('foo', (string) $s);
+ }
+}
diff --git a/server/vendor/guzzlehttp/psr7/tests/StreamWrapperTest.php b/server/vendor/guzzlehttp/psr7/tests/StreamWrapperTest.php
new file mode 100644
index 0000000..0156e59
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/tests/StreamWrapperTest.php
@@ -0,0 +1,100 @@
+<?php
+namespace GuzzleHttp\Tests\Psr7;
+
+use GuzzleHttp\Psr7\StreamWrapper;
+use GuzzleHttp\Psr7;
+
+/**
+ * @covers GuzzleHttp\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([
+ '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(['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(['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/server/vendor/guzzlehttp/psr7/tests/UriTest.php b/server/vendor/guzzlehttp/psr7/tests/UriTest.php
new file mode 100644
index 0000000..2776920
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/tests/UriTest.php
@@ -0,0 +1,247 @@
+<?php
+namespace GuzzleHttp\Tests\Psr7;
+
+use GuzzleHttp\Psr7\Uri;
+
+/**
+ * @covers GuzzleHttp\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()
+ {
+ new Uri('///');
+ }
+
+ public function testCanTransformAndRetrievePartsIndividually()
+ {
+ $uri = (new 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()
+ {
+ (new Uri(''))->withPort(100000);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testPathMustBeValid()
+ {
+ (new Uri(''))->withPath([]);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testQueryMustBeValid()
+ {
+ (new 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 [
+ //[self::RFC3986_BASE, 'g:h', 'g:h'],
+ [self::RFC3986_BASE, 'g', 'http://a/b/c/g'],
+ [self::RFC3986_BASE, './g', 'http://a/b/c/g'],
+ [self::RFC3986_BASE, 'g/', 'http://a/b/c/g/'],
+ [self::RFC3986_BASE, '/g', 'http://a/g'],
+ [self::RFC3986_BASE, '//g', 'http://g'],
+ [self::RFC3986_BASE, '?y', 'http://a/b/c/d;p?y'],
+ [self::RFC3986_BASE, 'g?y', 'http://a/b/c/g?y'],
+ [self::RFC3986_BASE, '#s', 'http://a/b/c/d;p?q#s'],
+ [self::RFC3986_BASE, 'g#s', 'http://a/b/c/g#s'],
+ [self::RFC3986_BASE, 'g?y#s', 'http://a/b/c/g?y#s'],
+ [self::RFC3986_BASE, ';x', 'http://a/b/c/;x'],
+ [self::RFC3986_BASE, 'g;x', 'http://a/b/c/g;x'],
+ [self::RFC3986_BASE, 'g;x?y#s', 'http://a/b/c/g;x?y#s'],
+ [self::RFC3986_BASE, '', self::RFC3986_BASE],
+ [self::RFC3986_BASE, '.', 'http://a/b/c/'],
+ [self::RFC3986_BASE, './', 'http://a/b/c/'],
+ [self::RFC3986_BASE, '..', 'http://a/b/'],
+ [self::RFC3986_BASE, '../', 'http://a/b/'],
+ [self::RFC3986_BASE, '../g', 'http://a/b/g'],
+ [self::RFC3986_BASE, '../..', 'http://a/'],
+ [self::RFC3986_BASE, '../../', 'http://a/'],
+ [self::RFC3986_BASE, '../../g', 'http://a/g'],
+ [self::RFC3986_BASE, '../../../g', 'http://a/g'],
+ [self::RFC3986_BASE, '../../../../g', 'http://a/g'],
+ [self::RFC3986_BASE, '/./g', 'http://a/g'],
+ [self::RFC3986_BASE, '/../g', 'http://a/g'],
+ [self::RFC3986_BASE, 'g.', 'http://a/b/c/g.'],
+ [self::RFC3986_BASE, '.g', 'http://a/b/c/.g'],
+ [self::RFC3986_BASE, 'g..', 'http://a/b/c/g..'],
+ [self::RFC3986_BASE, '..g', 'http://a/b/c/..g'],
+ [self::RFC3986_BASE, './../g', 'http://a/b/g'],
+ [self::RFC3986_BASE, 'foo////g', 'http://a/b/c/foo////g'],
+ [self::RFC3986_BASE, './g/.', 'http://a/b/c/g/'],
+ [self::RFC3986_BASE, 'g/./h', 'http://a/b/c/g/h'],
+ [self::RFC3986_BASE, 'g/../h', 'http://a/b/c/h'],
+ [self::RFC3986_BASE, 'g;x=1/./y', 'http://a/b/c/g;x=1/y'],
+ [self::RFC3986_BASE, 'g;x=1/../y', 'http://a/b/c/y'],
+ ['http://u@a/b/c/d;p?q', '.', 'http://u@a/b/c/'],
+ ['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 [
+ // Percent encode spaces.
+ ['http://foo.com/baz bar', 'http://foo.com/baz%20bar'],
+ // Don't encoding something that's already encoded.
+ ['http://foo.com/baz%20bar', 'http://foo.com/baz%20bar'],
+ // Percent encode invalid percent encodings
+ ['http://foo.com/baz%2-bar', 'http://foo.com/baz%252-bar'],
+ // Don't encode path segments
+ ['http://foo.com/baz/bar/bam?a', 'http://foo.com/baz/bar/bam?a'],
+ ['http://foo.com/baz+bar', 'http://foo.com/baz+bar'],
+ ['http://foo.com/baz:bar', 'http://foo.com/baz:bar'],
+ ['http://foo.com/baz@bar', 'http://foo.com/baz@bar'],
+ ['http://foo.com/baz(bar);bam/', 'http://foo.com/baz(bar);bam/'],
+ ['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()
+ {
+ $this->assertEquals('bar', new Uri('//bar'));
+ $this->assertEquals('bar', (new Uri('//bar'))->getHost());
+ }
+
+ public function testAllowsForRelativeUri()
+ {
+ $uri = (new Uri)->withPath('foo');
+ $this->assertEquals('foo', $uri->getPath());
+ $this->assertEquals('foo', (string) $uri);
+ }
+
+ public function testAddsSlashForRelativeUriStringWithHost()
+ {
+ $uri = (new Uri)->withPath('foo')->withHost('bar.com');
+ $this->assertEquals('foo', $uri->getPath());
+ $this->assertEquals('bar.com/foo', (string) $uri);
+ }
+}
diff --git a/server/vendor/guzzlehttp/psr7/tests/bootstrap.php b/server/vendor/guzzlehttp/psr7/tests/bootstrap.php
new file mode 100644
index 0000000..8601dd3
--- /dev/null
+++ b/server/vendor/guzzlehttp/psr7/tests/bootstrap.php
@@ -0,0 +1,11 @@
+<?php
+namespace GuzzleHttp\Tests\Psr7;
+
+require __DIR__ . '/../vendor/autoload.php';
+
+class HasToString
+{
+ public function __toString() {
+ return 'foo';
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/.gitattributes b/server/vendor/justinrainbow/json-schema/.gitattributes
new file mode 100644
index 0000000..beeff5b
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/.gitattributes
@@ -0,0 +1,5 @@
+/docs export-ignore
+/tests export-ignore
+.gitignore export-ignore
+.travis.yml export-ignore
+phpunit.dist.xml export-ignore
diff --git a/server/vendor/justinrainbow/json-schema/LICENSE b/server/vendor/justinrainbow/json-schema/LICENSE
new file mode 100644
index 0000000..6210e7c
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/LICENSE
@@ -0,0 +1,29 @@
+Copyright (c) 2008, Gradua Networks
+Author: Bruno Prieto Reis
+All rights reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of the Gradua Networks nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/server/vendor/justinrainbow/json-schema/README.md b/server/vendor/justinrainbow/json-schema/README.md
new file mode 100644
index 0000000..3f9c58c
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/README.md
@@ -0,0 +1,55 @@
+# JSON Schema for PHP
+
+[![Build Status](https://travis-ci.org/justinrainbow/json-schema.svg?branch=master)](https://travis-ci.org/justinrainbow/json-schema)
+[![Latest Stable Version](https://poser.pugx.org/justinrainbow/json-schema/v/stable.png)](https://packagist.org/packages/justinrainbow/json-schema)
+[![Total Downloads](https://poser.pugx.org/justinrainbow/json-schema/downloads.png)](https://packagist.org/packages/justinrainbow/json-schema)
+
+A PHP Implementation for validating `JSON` Structures against a given `Schema`.
+
+See [json-schema](http://json-schema.org/) for more details.
+
+## Installation
+
+### Library
+
+ $ git clone https://github.com/justinrainbow/json-schema.git
+
+### Dependencies
+
+#### [`Composer`](https://github.com/composer/composer) (*will use the Composer ClassLoader*)
+
+ $ wget http://getcomposer.org/composer.phar
+ $ php composer.phar require justinrainbow/json-schema:~1.3
+
+## Usage
+
+```php
+<?php
+
+// Get the schema and data as objects
+$retriever = new JsonSchema\Uri\UriRetriever;
+$schema = $retriever->retrieve('file://' . realpath('schema.json'));
+$data = json_decode(file_get_contents('data.json'));
+
+// If you use $ref or if you are unsure, resolve those references here
+// This modifies the $schema object
+$refResolver = new JsonSchema\RefResolver($retriever);
+$refResolver->resolve($schema, 'file://' . __DIR__);
+
+// Validate
+$validator = new JsonSchema\Validator();
+$validator->check($data, $schema);
+
+if ($validator->isValid()) {
+ echo "The supplied JSON validates against the schema.\n";
+} else {
+ echo "JSON does not validate. Violations:\n";
+ foreach ($validator->getErrors() as $error) {
+ echo sprintf("[%s] %s\n", $error['property'], $error['message']);
+ }
+}
+```
+
+## Running the tests
+
+ $ vendor/bin/phpunit
diff --git a/server/vendor/justinrainbow/json-schema/bin/validate-json b/server/vendor/justinrainbow/json-schema/bin/validate-json
new file mode 100755
index 0000000..e93d53a
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/bin/validate-json
@@ -0,0 +1,245 @@
+#!/usr/bin/env php
+<?php
+/**
+ * JSON schema validator
+ *
+ * @author Christian Weiske <christian.weiske@netresearch.de>
+ */
+
+/**
+ * Dead simple autoloader
+ *
+ * @param string $className Name of class to load
+ *
+ * @return void
+ */
+function __autoload($className)
+{
+ $className = ltrim($className, '\\');
+ $fileName = '';
+ $namespace = '';
+ if ($lastNsPos = strrpos($className, '\\')) {
+ $namespace = substr($className, 0, $lastNsPos);
+ $className = substr($className, $lastNsPos + 1);
+ $fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
+ }
+ $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
+ if (stream_resolve_include_path($fileName)) {
+ require_once $fileName;
+ }
+}
+
+/**
+ * Show the json parse error that happened last
+ *
+ * @return void
+ */
+function showJsonError()
+{
+ $constants = get_defined_constants(true);
+ $json_errors = array();
+ foreach ($constants['json'] as $name => $value) {
+ if (!strncmp($name, 'JSON_ERROR_', 11)) {
+ $json_errors[$value] = $name;
+ }
+ }
+
+ echo 'JSON parse error: ' . $json_errors[json_last_error()] . "\n";
+}
+
+function getUrlFromPath($path)
+{
+ if (parse_url($path, PHP_URL_SCHEME) !== null) {
+ //already an URL
+ return $path;
+ }
+ if ($path{0} == '/') {
+ //absolute path
+ return 'file://' . $path;
+ }
+
+ //relative path: make absolute
+ return 'file://' . getcwd() . '/' . $path;
+}
+
+/**
+ * Take a HTTP header value and split it up into parts.
+ *
+ * @return array Key "_value" contains the main value, all others
+ * as given in the header value
+ */
+function parseHeaderValue($headerValue)
+{
+ if (strpos($headerValue, ';') === false) {
+ return array('_value' => $headerValue);
+ }
+
+ $parts = explode(';', $headerValue);
+ $arData = array('_value' => array_shift($parts));
+ foreach ($parts as $part) {
+ list($name, $value) = explode('=', $part);
+ $arData[$name] = trim($value, ' "\'');
+ }
+ return $arData;
+}
+
+
+// support running this tool from git checkout
+if (is_dir(__DIR__ . '/../src/JsonSchema')) {
+ set_include_path(__DIR__ . '/../src' . PATH_SEPARATOR . get_include_path());
+}
+
+$arOptions = array();
+$arArgs = array();
+array_shift($argv);//script itself
+foreach ($argv as $arg) {
+ if ($arg{0} == '-') {
+ $arOptions[$arg] = true;
+ } else {
+ $arArgs[] = $arg;
+ }
+}
+
+if (count($arArgs) == 0
+ || isset($arOptions['--help']) || isset($arOptions['-h'])
+) {
+ echo <<<HLP
+Validate schema
+Usage: validate-json data.json
+ or: validate-json data.json schema.json
+
+Options:
+ --dump-schema Output full schema and exit
+ --dump-schema-url Output URL of schema
+ -h --help Show this help
+
+HLP;
+ exit(1);
+}
+
+if (count($arArgs) == 1) {
+ $pathData = $arArgs[0];
+ $pathSchema = null;
+} else {
+ $pathData = $arArgs[0];
+ $pathSchema = getUrlFromPath($arArgs[1]);
+}
+
+$urlData = getUrlFromPath($pathData);
+
+$context = stream_context_create(
+ array(
+ 'http' => array(
+ 'header' => array(
+ 'Accept: */*',
+ 'Connection: Close'
+ ),
+ 'max_redirects' => 5
+ )
+ )
+);
+$dataString = file_get_contents($pathData, false, $context);
+if ($dataString == '') {
+ echo "Data file is not readable or empty.\n";
+ exit(3);
+}
+
+$data = json_decode($dataString);
+unset($dataString);
+if ($data === null) {
+ echo "Error loading JSON data file\n";
+ showJsonError();
+ exit(5);
+}
+
+if ($pathSchema === null) {
+ if (isset($http_response_header)) {
+ array_shift($http_response_header);//HTTP/1.0 line
+ foreach ($http_response_header as $headerLine) {
+ list($hName, $hValue) = explode(':', $headerLine, 2);
+ $hName = strtolower($hName);
+ if ($hName == 'link') {
+ //Link: <http://example.org/schema#>; rel="describedBy"
+ $hParts = parseHeaderValue($hValue);
+ if (isset($hParts['rel']) && $hParts['rel'] == 'describedBy') {
+ $pathSchema = trim($hParts['_value'], ' <>');
+ }
+ } else if ($hName == 'content-type') {
+ //Content-Type: application/my-media-type+json;
+ // profile=http://example.org/schema#
+ $hParts = parseHeaderValue($hValue);
+ if (isset($hParts['profile'])) {
+ $pathSchema = $hParts['profile'];
+ }
+
+ }
+ }
+ }
+ if (is_object($data) && property_exists($data, '$schema')) {
+ $pathSchema = $data->{'$schema'};
+ }
+
+ //autodetect schema
+ if ($pathSchema === null) {
+ echo "JSON data must be an object and have a \$schema property.\n";
+ echo "You can pass the schema file on the command line as well.\n";
+ echo "Schema autodetection failed.\n";
+ exit(6);
+ }
+}
+if ($pathSchema{0} == '/') {
+ $pathSchema = 'file://' . $pathSchema;
+}
+
+$resolver = new JsonSchema\Uri\UriResolver();
+$retriever = new JsonSchema\Uri\UriRetriever();
+try {
+ $urlSchema = $resolver->resolve($pathSchema, $urlData);
+
+ if (isset($arOptions['--dump-schema-url'])) {
+ echo $urlSchema . "\n";
+ exit();
+ }
+
+ $schema = $retriever->retrieve($urlSchema);
+ if ($schema === null) {
+ echo "Error loading JSON schema file\n";
+ echo $urlSchema . "\n";
+ showJsonError();
+ exit(2);
+ }
+} catch (Exception $e) {
+ echo "Error loading JSON schema file\n";
+ echo $urlSchema . "\n";
+ echo $e->getMessage() . "\n";
+ exit(2);
+}
+$refResolver = new JsonSchema\RefResolver($retriever);
+$refResolver->resolve($schema, $urlSchema);
+
+if (isset($arOptions['--dump-schema'])) {
+ $options = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0;
+ echo json_encode($schema, $options) . "\n";
+ exit();
+}
+
+try {
+ $validator = new JsonSchema\Validator();
+ $validator->check($data, $schema);
+
+ if ($validator->isValid()) {
+ echo "OK. The supplied JSON validates against the schema.\n";
+ } else {
+ echo "JSON does not validate. Violations:\n";
+ foreach ($validator->getErrors() as $error) {
+ echo sprintf("[%s] %s\n", $error['property'], $error['message']);
+ }
+ exit(23);
+ }
+} catch (Exception $e) {
+ echo "JSON does not validate. Error:\n";
+ echo $e->getMessage() . "\n";
+ echo "Error code: " . $e->getCode() . "\n";
+ exit(24);
+}
+?>
diff --git a/server/vendor/justinrainbow/json-schema/composer.json b/server/vendor/justinrainbow/json-schema/composer.json
new file mode 100644
index 0000000..c45891a
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/composer.json
@@ -0,0 +1,58 @@
+{
+ "name": "justinrainbow/json-schema",
+ "description": "A library to validate a json schema.",
+ "keywords": ["json", "schema"],
+ "homepage": "https://github.com/justinrainbow/json-schema",
+ "type": "library",
+ "license": "BSD-3-Clause",
+ "authors": [
+ {
+ "name": "Bruno Prieto Reis",
+ "email": "bruno.p.reis@gmail.com"
+ },
+ {
+ "name": "Justin Rainbow",
+ "email": "justin.rainbow@gmail.com"
+ },
+ {
+ "name": "Igor Wiedler",
+ "email": "igor@wiedler.ch"
+ },
+ {
+ "name": "Robert Schönthal",
+ "email": "seroscho@googlemail.com"
+ }
+ ],
+ "repositories": [{
+ "type": "package",
+ "package": {
+ "name": "json-schema/JSON-Schema-Test-Suite",
+ "version": "1.1.0",
+ "source": {
+ "url": "https://github.com/json-schema/JSON-Schema-Test-Suite",
+ "type": "git",
+ "reference": "1.1.0"
+ }
+ }
+ }],
+ "require": {
+ "php": ">=5.3.2"
+ },
+ "require-dev": {
+ "json-schema/JSON-Schema-Test-Suite": "1.1.0",
+ "phpunit/phpunit": "~3.7",
+ "phpdocumentor/phpdocumentor": "~2"
+ },
+ "autoload": {
+ "psr-4": { "JsonSchema\\": "src/JsonSchema/" }
+ },
+ "autoload-dev": {
+ "psr-4": { "JsonSchema\\Tests\\": "tests/JsonSchema/Tests/" }
+ },
+ "bin": ["bin/validate-json"],
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.4.x-dev"
+ }
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/phpunit.xml.dist b/server/vendor/justinrainbow/json-schema/phpunit.xml.dist
new file mode 100644
index 0000000..0136d8e
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/phpunit.xml.dist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit backupGlobals="false"
+ backupStaticAttributes="false"
+ colors="true"
+ convertErrorsToExceptions="true"
+ convertNoticesToExceptions="true"
+ convertWarningsToExceptions="true"
+ processIsolation="false"
+ stopOnFailure="false"
+ syntaxCheck="false"
+ bootstrap="vendor/autoload.php"
+ verbose="true"
+>
+ <testsuites>
+ <testsuite name="JSON Schema Test Suite">
+ <directory>tests</directory>
+ </testsuite>
+ </testsuites>
+
+ <filter>
+ <whitelist>
+ <directory>./src/JsonSchema/</directory>
+ </whitelist>
+ </filter>
+</phpunit>
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php
new file mode 100644
index 0000000..b43bace
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php
@@ -0,0 +1,112 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+/**
+ * The CollectionConstraint Constraints, validates an array against a given schema
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
+ */
+class CollectionConstraint extends Constraint
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function check($value, $schema = null, $path = null, $i = null)
+ {
+ // Verify minItems
+ if (isset($schema->minItems) && count($value) < $schema->minItems) {
+ $this->addError($path, "There must be a minimum of " . $schema->minItems . " items in the array", 'minItems', array('minItems' => $schema->minItems,));
+ }
+
+ // Verify maxItems
+ if (isset($schema->maxItems) && count($value) > $schema->maxItems) {
+ $this->addError($path, "There must be a maximum of " . $schema->maxItems . " items in the array", 'maxItems', array('maxItems' => $schema->maxItems,));
+ }
+
+ // Verify uniqueItems
+ if (isset($schema->uniqueItems) && $schema->uniqueItems) {
+ $unique = $value;
+ if (is_array($value) && count($value)) {
+ $unique = array_map(function($e) { return var_export($e, true); }, $value);
+ }
+ if (count(array_unique($unique)) != count($value)) {
+ $this->addError($path, "There are no duplicates allowed in the array", 'uniqueItems');
+ }
+ }
+
+ // Verify items
+ if (isset($schema->items)) {
+ $this->validateItems($value, $schema, $path, $i);
+ }
+ }
+
+ /**
+ * Validates the items
+ *
+ * @param array $value
+ * @param \stdClass $schema
+ * @param string $path
+ * @param string $i
+ */
+ protected function validateItems($value, $schema = null, $path = null, $i = null)
+ {
+ if (is_object($schema->items)) {
+ // just one type definition for the whole array
+ foreach ($value as $k => $v) {
+ $initErrors = $this->getErrors();
+
+ // First check if its defined in "items"
+ $this->checkUndefined($v, $schema->items, $path, $k);
+
+ // Recheck with "additionalItems" if the first test fails
+ if (count($initErrors) < count($this->getErrors()) && (isset($schema->additionalItems) && $schema->additionalItems !== false)) {
+ $secondErrors = $this->getErrors();
+ $this->checkUndefined($v, $schema->additionalItems, $path, $k);
+ }
+
+ // Reset errors if needed
+ if (isset($secondErrors) && count($secondErrors) < count($this->getErrors())) {
+ $this->errors = $secondErrors;
+ } else if (isset($secondErrors) && count($secondErrors) === count($this->getErrors())) {
+ $this->errors = $initErrors;
+ }
+ }
+ } else {
+ // Defined item type definitions
+ foreach ($value as $k => $v) {
+ if (array_key_exists($k, $schema->items)) {
+ $this->checkUndefined($v, $schema->items[$k], $path, $k);
+ } else {
+ // Additional items
+ if (property_exists($schema, 'additionalItems')) {
+ if ($schema->additionalItems !== false) {
+ $this->checkUndefined($v, $schema->additionalItems, $path, $k);
+ } else {
+ $this->addError(
+ $path, 'The item ' . $i . '[' . $k . '] is not defined and the definition does not allow additional items', 'additionalItems', array('additionalItems' => $schema->additionalItems,));
+ }
+ } else {
+ // Should be valid against an empty schema
+ $this->checkUndefined($v, new \stdClass(), $path, $k);
+ }
+ }
+ }
+
+ // Treat when we have more schema definitions than values, not for empty arrays
+ if(count($value) > 0) {
+ for ($k = count($value); $k < count($schema->items); $k++) {
+ $this->checkUndefined(new UndefinedConstraint(), $schema->items[$k], $path, $k);
+ }
+ }
+ }
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php
new file mode 100644
index 0000000..cb3ee80
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php
@@ -0,0 +1,291 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+use JsonSchema\Uri\UriRetriever;
+
+/**
+ * The Base Constraints, all Validators should extend this class
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
+ */
+abstract class Constraint implements ConstraintInterface
+{
+ protected $checkMode = self::CHECK_MODE_NORMAL;
+ protected $uriRetriever;
+ protected $errors = array();
+ protected $inlineSchemaProperty = '$schema';
+
+ const CHECK_MODE_NORMAL = 1;
+ const CHECK_MODE_TYPE_CAST = 2;
+
+ /**
+ * @var null|Factory
+ */
+ private $factory;
+
+ /**
+ * @param int $checkMode
+ * @param UriRetriever $uriRetriever
+ * @param Factory $factory
+ */
+ public function __construct($checkMode = self::CHECK_MODE_NORMAL, UriRetriever $uriRetriever = null, Factory $factory = null)
+ {
+ $this->checkMode = $checkMode;
+ $this->uriRetriever = $uriRetriever;
+ $this->factory = $factory;
+ }
+
+ /**
+ * @return UriRetriever $uriRetriever
+ */
+ public function getUriRetriever()
+ {
+ if (is_null($this->uriRetriever))
+ {
+ $this->setUriRetriever(new UriRetriever);
+ }
+
+ return $this->uriRetriever;
+ }
+
+ /**
+ * @return Factory
+ */
+ public function getFactory()
+ {
+ if (!$this->factory) {
+ $this->factory = new Factory($this->getUriRetriever());
+ }
+
+ return $this->factory;
+ }
+
+ /**
+ * @param UriRetriever $uriRetriever
+ */
+ public function setUriRetriever(UriRetriever $uriRetriever)
+ {
+ $this->uriRetriever = $uriRetriever;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function addError($path, $message, $constraint='', array $more=null)
+ {
+ $error = array(
+ 'property' => $path,
+ 'message' => $message,
+ 'constraint' => $constraint,
+ );
+
+ if (is_array($more) && count($more) > 0)
+ {
+ $error += $more;
+ }
+
+ $this->errors[] = $error;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function addErrors(array $errors)
+ {
+ $this->errors = array_merge($this->errors, $errors);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getErrors()
+ {
+ return $this->errors;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function isValid()
+ {
+ return !$this->getErrors();
+ }
+
+ /**
+ * Clears any reported errors. Should be used between
+ * multiple validation checks.
+ */
+ public function reset()
+ {
+ $this->errors = array();
+ }
+
+ /**
+ * Bubble down the path
+ *
+ * @param string $path Current path
+ * @param mixed $i What to append to the path
+ *
+ * @return string
+ */
+ protected function incrementPath($path, $i)
+ {
+ if ($path !== '') {
+ if (is_int($i)) {
+ $path .= '[' . $i . ']';
+ } elseif ($i == '') {
+ $path .= '';
+ } else {
+ $path .= '.' . $i;
+ }
+ } else {
+ $path = $i;
+ }
+
+ return $path;
+ }
+
+ /**
+ * Validates an array
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param mixed $path
+ * @param mixed $i
+ */
+ protected function checkArray($value, $schema = null, $path = null, $i = null)
+ {
+ $validator = $this->getFactory()->createInstanceFor('collection');
+ $validator->check($value, $schema, $path, $i);
+
+ $this->addErrors($validator->getErrors());
+ }
+
+ /**
+ * Validates an object
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param mixed $path
+ * @param mixed $i
+ * @param mixed $patternProperties
+ */
+ protected function checkObject($value, $schema = null, $path = null, $i = null, $patternProperties = null)
+ {
+ $validator = $this->getFactory()->createInstanceFor('object');
+ $validator->check($value, $schema, $path, $i, $patternProperties);
+
+ $this->addErrors($validator->getErrors());
+ }
+
+ /**
+ * Validates the type of a property
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param mixed $path
+ * @param mixed $i
+ */
+ protected function checkType($value, $schema = null, $path = null, $i = null)
+ {
+ $validator = $this->getFactory()->createInstanceFor('type');
+ $validator->check($value, $schema, $path, $i);
+
+ $this->addErrors($validator->getErrors());
+ }
+
+ /**
+ * Checks a undefined element
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param mixed $path
+ * @param mixed $i
+ */
+ protected function checkUndefined($value, $schema = null, $path = null, $i = null)
+ {
+ $validator = $this->getFactory()->createInstanceFor('undefined');
+ $validator->check($value, $schema, $path, $i);
+
+ $this->addErrors($validator->getErrors());
+ }
+
+ /**
+ * Checks a string element
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param mixed $path
+ * @param mixed $i
+ */
+ protected function checkString($value, $schema = null, $path = null, $i = null)
+ {
+ $validator = $this->getFactory()->createInstanceFor('string');
+ $validator->check($value, $schema, $path, $i);
+
+ $this->addErrors($validator->getErrors());
+ }
+
+ /**
+ * Checks a number element
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param mixed $path
+ * @param mixed $i
+ */
+ protected function checkNumber($value, $schema = null, $path = null, $i = null)
+ {
+ $validator = $this->getFactory()->createInstanceFor('number');
+ $validator->check($value, $schema, $path, $i);
+
+ $this->addErrors($validator->getErrors());
+ }
+
+ /**
+ * Checks a enum element
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param mixed $path
+ * @param mixed $i
+ */
+ protected function checkEnum($value, $schema = null, $path = null, $i = null)
+ {
+ $validator = $this->getFactory()->createInstanceFor('enum');
+ $validator->check($value, $schema, $path, $i);
+
+ $this->addErrors($validator->getErrors());
+ }
+
+ protected function checkFormat($value, $schema = null, $path = null, $i = null)
+ {
+ $validator = $this->getFactory()->createInstanceFor('format');
+ $validator->check($value, $schema, $path, $i);
+
+ $this->addErrors($validator->getErrors());
+ }
+
+ /**
+ * @param string $uri JSON Schema URI
+ * @return string JSON Schema contents
+ */
+ protected function retrieveUri($uri)
+ {
+ if (null === $this->uriRetriever) {
+ $this->setUriRetriever(new UriRetriever);
+ }
+ $jsonSchema = $this->uriRetriever->retrieve($uri);
+ // TODO validate using schema
+ return $jsonSchema;
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php
new file mode 100644
index 0000000..34280f4
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+/**
+ * The Constraints Interface
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ */
+interface ConstraintInterface
+{
+ /**
+ * returns all collected errors
+ *
+ * @return array
+ */
+ public function getErrors();
+
+ /**
+ * adds errors to this validator
+ *
+ * @param array $errors
+ */
+ public function addErrors(array $errors);
+
+ /**
+ * adds an error
+ *
+ * @param string $path
+ * @param string $message
+ * @param string $constraint the constraint/rule that is broken, e.g.: 'minLength'
+ * @param array $more more array elements to add to the error
+ */
+ public function addError($path, $message, $constraint='', array $more=null);
+
+ /**
+ * checks if the validator has not raised errors
+ *
+ * @return boolean
+ */
+ public function isValid();
+
+ /**
+ * invokes the validation of an element
+ *
+ * @abstract
+ * @param mixed $value
+ * @param mixed $schema
+ * @param mixed $path
+ * @param mixed $i
+ */
+ public function check($value, $schema = null, $path = null, $i = null);
+} \ No newline at end of file
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php
new file mode 100644
index 0000000..df413e4
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php
@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+/**
+ * The EnumConstraint Constraints, validates an element against a given set of possibilities
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
+ */
+class EnumConstraint extends Constraint
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function check($element, $schema = null, $path = null, $i = null)
+ {
+ // Only validate enum if the attribute exists
+ if ($element instanceof UndefinedConstraint && (!isset($schema->required) || !$schema->required)) {
+ return;
+ }
+
+ foreach ($schema->enum as $enum) {
+ $type = gettype($element);
+ if ($type === gettype($enum)) {
+ if ($type == "object") {
+ if ($element == $enum)
+ return;
+ } else {
+ if ($element === $enum)
+ return;
+
+ }
+ }
+ }
+
+ $this->addError($path, "Does not have a value in the enumeration " . print_r($schema->enum, true), 'enum', array('enum' => $schema->enum,));
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php
new file mode 100644
index 0000000..a4570f6
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php
@@ -0,0 +1,81 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+use JsonSchema\Exception\InvalidArgumentException;
+use JsonSchema\Uri\UriRetriever;
+use JsonSchema\Validator;
+
+/**
+ * Factory for centralize constraint initialization.
+ */
+class Factory
+{
+ /**
+ * @var UriRetriever
+ */
+ protected $uriRetriever;
+
+ /**
+ * @param UriRetriever $uriRetriever
+ */
+ public function __construct(UriRetriever $uriRetriever = null)
+ {
+ if (!$uriRetriever) {
+ $uriRetriever = new UriRetriever();
+ }
+
+ $this->uriRetriever = $uriRetriever;
+ }
+
+ /**
+ * @return UriRetriever
+ */
+ public function getUriRetriever()
+ {
+ return $this->uriRetriever;
+ }
+
+ /**
+ * Create a constraint instance for the given constraint name.
+ *
+ * @param string $constraintName
+ * @return ConstraintInterface|ObjectConstraint
+ * @throws InvalidArgumentException if is not possible create the constraint instance.
+ */
+ public function createInstanceFor($constraintName)
+ {
+ switch ($constraintName) {
+ case 'array':
+ case 'collection':
+ return new CollectionConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ case 'object':
+ return new ObjectConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ case 'type':
+ return new TypeConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ case 'undefined':
+ return new UndefinedConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ case 'string':
+ return new StringConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ case 'number':
+ return new NumberConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ case 'enum':
+ return new EnumConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ case 'format':
+ return new FormatConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ case 'schema':
+ return new SchemaConstraint(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ case 'validator':
+ return new Validator(Constraint::CHECK_MODE_NORMAL, $this->uriRetriever, $this);
+ }
+
+ throw new InvalidArgumentException('Unknown constraint ' . $constraintName);
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php
new file mode 100644
index 0000000..c789753
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php
@@ -0,0 +1,181 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+/**
+ * Validates against the "format" property
+ *
+ * @author Justin Rainbow <justin.rainbow@gmail.com>
+ * @link http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.23
+ */
+class FormatConstraint extends Constraint
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function check($element, $schema = null, $path = null, $i = null)
+ {
+ if (!isset($schema->format)) {
+ return;
+ }
+
+ switch ($schema->format) {
+ case 'date':
+ if (!$date = $this->validateDateTime($element, 'Y-m-d')) {
+ $this->addError($path, sprintf('Invalid date %s, expected format YYYY-MM-DD', json_encode($element)), 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'time':
+ if (!$this->validateDateTime($element, 'H:i:s')) {
+ $this->addError($path, sprintf('Invalid time %s, expected format hh:mm:ss', json_encode($element)), 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'date-time':
+ if (!$this->validateDateTime($element, 'Y-m-d\TH:i:s\Z') &&
+ !$this->validateDateTime($element, 'Y-m-d\TH:i:s.u\Z') &&
+ !$this->validateDateTime($element, 'Y-m-d\TH:i:sP') &&
+ !$this->validateDateTime($element, 'Y-m-d\TH:i:sO')
+ ) {
+ $this->addError($path, sprintf('Invalid date-time %s, expected format YYYY-MM-DDThh:mm:ssZ or YYYY-MM-DDThh:mm:ss+hh:mm', json_encode($element)), 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'utc-millisec':
+ if (!$this->validateDateTime($element, 'U')) {
+ $this->addError($path, sprintf('Invalid time %s, expected integer of milliseconds since Epoch', json_encode($element)), 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'regex':
+ if (!$this->validateRegex($element)) {
+ $this->addError($path, 'Invalid regex format ' . $element, 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'color':
+ if (!$this->validateColor($element)) {
+ $this->addError($path, "Invalid color", 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'style':
+ if (!$this->validateStyle($element)) {
+ $this->addError($path, "Invalid style", 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'phone':
+ if (!$this->validatePhone($element)) {
+ $this->addError($path, "Invalid phone number", 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'uri':
+ if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
+ $this->addError($path, "Invalid URL format", 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'email':
+ if (null === filter_var($element, FILTER_VALIDATE_EMAIL, FILTER_NULL_ON_FAILURE)) {
+ $this->addError($path, "Invalid email", 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'ip-address':
+ case 'ipv4':
+ if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4)) {
+ $this->addError($path, "Invalid IP address", 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'ipv6':
+ if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV6)) {
+ $this->addError($path, "Invalid IP address", 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ case 'host-name':
+ case 'hostname':
+ if (!$this->validateHostname($element)) {
+ $this->addError($path, "Invalid hostname", 'format', array('format' => $schema->format,));
+ }
+ break;
+
+ default:
+ // Empty as it should be:
+ // The value of this keyword is called a format attribute. It MUST be a string.
+ // A format attribute can generally only validate a given set of instance types.
+ // If the type of the instance to validate is not in this set, validation for
+ // this format attribute and instance SHOULD succeed.
+ // http://json-schema.org/latest/json-schema-validation.html#anchor105
+ break;
+ }
+ }
+
+ protected function validateDateTime($datetime, $format)
+ {
+ $dt = \DateTime::createFromFormat($format, $datetime);
+
+ if (!$dt) {
+ return false;
+ }
+
+ if ($datetime === $dt->format($format)) {
+ return true;
+ }
+
+ // handles the case where a non-6 digit microsecond datetime is passed
+ // which will fail the above string comparison because the passed
+ // $datetime may be '2000-05-01T12:12:12.123Z' but format() will return
+ // '2000-05-01T12:12:12.123000Z'
+ if ((strpos('u', $format) !== -1) && (intval($dt->format('u')) > 0)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ protected function validateRegex($regex)
+ {
+ return false !== @preg_match('/' . $regex . '/', '');
+ }
+
+ protected function validateColor($color)
+ {
+ if (in_array(strtolower($color), array('aqua', 'black', 'blue', 'fuchsia',
+ 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple',
+ 'red', 'silver', 'teal', 'white', 'yellow'))) {
+ return true;
+ }
+
+ return preg_match('/^#([a-f0-9]{3}|[a-f0-9]{6})$/i', $color);
+ }
+
+ protected function validateStyle($style)
+ {
+ $properties = explode(';', rtrim($style, ';'));
+ $invalidEntries = preg_grep('/^\s*[-a-z]+\s*:\s*.+$/i', $properties, PREG_GREP_INVERT);
+
+ return empty($invalidEntries);
+ }
+
+ protected function validatePhone($phone)
+ {
+ return preg_match('/^\+?(\(\d{3}\)|\d{3}) \d{3} \d{4}$/', $phone);
+ }
+
+ protected function validateHostname($host)
+ {
+ return preg_match('/^[_a-z]+\.([_a-z]+\.?)+$/i', $host);
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php
new file mode 100644
index 0000000..0a34bdc
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php
@@ -0,0 +1,83 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+/**
+ * The NumberConstraint Constraints, validates an number against a given schema
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
+ */
+class NumberConstraint extends Constraint
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function check($element, $schema = null, $path = null, $i = null)
+ {
+ // Verify minimum
+ if (isset($schema->exclusiveMinimum)) {
+ if (isset($schema->minimum)) {
+ if ($schema->exclusiveMinimum && $element === $schema->minimum) {
+ $this->addError($path, "Must have a minimum value greater than boundary value of " . $schema->minimum, 'exclusiveMinimum', array('minimum' => $schema->minimum,));
+ } else if ($element < $schema->minimum) {
+ $this->addError($path, "Must have a minimum value of " . $schema->minimum, 'minimum', array('minimum' => $schema->minimum,));
+ }
+ } else {
+ $this->addError($path, "Use of exclusiveMinimum requires presence of minimum", 'missingMinimum');
+ }
+ } else if (isset($schema->minimum) && $element < $schema->minimum) {
+ $this->addError($path, "Must have a minimum value of " . $schema->minimum, 'minimum', array('minimum' => $schema->minimum,));
+ }
+
+ // Verify maximum
+ if (isset($schema->exclusiveMaximum)) {
+ if (isset($schema->maximum)) {
+ if ($schema->exclusiveMaximum && $element === $schema->maximum) {
+ $this->addError($path, "Must have a maximum value less than boundary value of " . $schema->maximum, 'exclusiveMaximum', array('maximum' => $schema->maximum,));
+ } else if ($element > $schema->maximum) {
+ $this->addError($path, "Must have a maximum value of " . $schema->maximum, 'maximum', array('maximum' => $schema->maximum,));
+ }
+ } else {
+ $this->addError($path, "Use of exclusiveMaximum requires presence of maximum", 'missingMinimum');
+ }
+ } else if (isset($schema->maximum) && $element > $schema->maximum) {
+ $this->addError($path, "Must have a maximum value of " . $schema->maximum, 'maximum', array('maximum' => $schema->maximum,));
+ }
+
+ // Verify divisibleBy - Draft v3
+ if (isset($schema->divisibleBy) && $this->fmod($element, $schema->divisibleBy) != 0) {
+ $this->addError($path, "Is not divisible by " . $schema->divisibleBy, 'divisibleBy', array('divisibleBy' => $schema->divisibleBy,));
+ }
+
+ // Verify multipleOf - Draft v4
+ if (isset($schema->multipleOf) && $this->fmod($element, $schema->multipleOf) != 0) {
+ $this->addError($path, "Must be a multiple of " . $schema->multipleOf, 'multipleOf', array('multipleOf' => $schema->multipleOf,));
+ }
+
+ $this->checkFormat($element, $schema, $path, $i);
+ }
+
+ private function fmod($number1, $number2)
+ {
+ $modulus = fmod($number1, $number2);
+ $precision = abs(0.0000000001);
+ $diff = (float)($modulus - $number2);
+
+ if (-$precision < $diff && $diff < $precision) {
+ return 0.0;
+ }
+
+ $decimals1 = mb_strpos($number1, ".") ? mb_strlen($number1) - mb_strpos($number1, ".") - 1 : 0;
+ $decimals2 = mb_strpos($number2, ".") ? mb_strlen($number2) - mb_strpos($number2, ".") - 1 : 0;
+
+ return (float)round($modulus, max($decimals1, $decimals2));
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php
new file mode 100644
index 0000000..0e5cf1b
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php
@@ -0,0 +1,149 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+/**
+ * The ObjectConstraint Constraints, validates an object against a given schema
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
+ */
+class ObjectConstraint extends Constraint
+{
+ /**
+ * {@inheritDoc}
+ */
+ function check($element, $definition = null, $path = null, $additionalProp = null, $patternProperties = null)
+ {
+ if ($element instanceof UndefinedConstraint) {
+ return;
+ }
+
+ $matches = array();
+ if ($patternProperties) {
+ $matches = $this->validatePatternProperties($element, $path, $patternProperties);
+ }
+
+ if ($definition) {
+ // validate the definition properties
+ $this->validateDefinition($element, $definition, $path);
+ }
+
+ // additional the element properties
+ $this->validateElement($element, $matches, $definition, $path, $additionalProp);
+ }
+
+ public function validatePatternProperties($element, $path, $patternProperties)
+ {
+ $try = array('/','#','+','~','%');
+ $matches = array();
+ foreach ($patternProperties as $pregex => $schema) {
+ $delimiter = '/';
+ // Choose delimiter. Necessary for patterns like ^/ , otherwise you get error
+ foreach ($try as $delimiter) {
+ if (strpos($pregex, $delimiter) === false) { // safe to use
+ break;
+ }
+ }
+
+ // Validate the pattern before using it to test for matches
+ if (@preg_match($delimiter. $pregex . $delimiter, '') === false) {
+ $this->addError($path, 'The pattern "' . $pregex . '" is invalid', 'pregex', array('pregex' => $pregex,));
+ continue;
+ }
+ foreach ($element as $i => $value) {
+ if (preg_match($delimiter . $pregex . $delimiter, $i)) {
+ $matches[] = $i;
+ $this->checkUndefined($value, $schema ? : new \stdClass(), $path, $i);
+ }
+ }
+ }
+ return $matches;
+ }
+
+ /**
+ * Validates the element properties
+ *
+ * @param \stdClass $element Element to validate
+ * @param array $matches Matches from patternProperties (if any)
+ * @param \stdClass $objectDefinition ObjectConstraint definition
+ * @param string $path Path to test?
+ * @param mixed $additionalProp Additional properties
+ */
+ public function validateElement($element, $matches, $objectDefinition = null, $path = null, $additionalProp = null)
+ {
+ foreach ($element as $i => $value) {
+
+ $property = $this->getProperty($element, $i, new UndefinedConstraint());
+ $definition = $this->getProperty($objectDefinition, $i);
+
+ // no additional properties allowed
+ if (!in_array($i, $matches) && $additionalProp === false && $this->inlineSchemaProperty !== $i && !$definition) {
+ $this->addError($path, "The property " . $i . " is not defined and the definition does not allow additional properties", 'additionalProp');
+ }
+
+ // additional properties defined
+ if (!in_array($i, $matches) && $additionalProp && !$definition) {
+ if ($additionalProp === true) {
+ $this->checkUndefined($value, null, $path, $i);
+ } else {
+ $this->checkUndefined($value, $additionalProp, $path, $i);
+ }
+ }
+
+ // property requires presence of another
+ $require = $this->getProperty($definition, 'requires');
+ if ($require && !$this->getProperty($element, $require)) {
+ $this->addError($path, "The presence of the property " . $i . " requires that " . $require . " also be present", 'requires');
+ }
+
+ if (!$definition) {
+ // normal property verification
+ $this->checkUndefined($value, new \stdClass(), $path, $i);
+ }
+ }
+ }
+
+ /**
+ * Validates the definition properties
+ *
+ * @param \stdClass $element Element to validate
+ * @param \stdClass $objectDefinition ObjectConstraint definition
+ * @param string $path Path?
+ */
+ public function validateDefinition($element, $objectDefinition = null, $path = null)
+ {
+ foreach ($objectDefinition as $i => $value) {
+ $property = $this->getProperty($element, $i, new UndefinedConstraint());
+ $definition = $this->getProperty($objectDefinition, $i);
+ $this->checkUndefined($property, $definition, $path, $i);
+ }
+ }
+
+ /**
+ * retrieves a property from an object or array
+ *
+ * @param mixed $element Element to validate
+ * @param string $property Property to retrieve
+ * @param mixed $fallback Default value if property is not found
+ *
+ * @return mixed
+ */
+ protected function getProperty($element, $property, $fallback = null)
+ {
+ if (is_array($element) /*$this->checkMode == self::CHECK_MODE_TYPE_CAST*/) {
+ return array_key_exists($property, $element) ? $element[$property] : $fallback;
+ } elseif (is_object($element)) {
+ return property_exists($element, $property) ? $element->$property : $fallback;
+ }
+
+ return $fallback;
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php
new file mode 100644
index 0000000..b856a11
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+use JsonSchema\Exception\InvalidArgumentException;
+
+/**
+ * The SchemaConstraint Constraints, validates an element against a given schema
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
+ */
+class SchemaConstraint extends Constraint
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function check($element, $schema = null, $path = null, $i = null)
+ {
+ if ($schema !== null) {
+ // passed schema
+ $this->checkUndefined($element, $schema, '', '');
+ } elseif (property_exists($element, $this->inlineSchemaProperty)) {
+ // inline schema
+ $this->checkUndefined($element, $element->{$this->inlineSchemaProperty}, '', '');
+ } else {
+ throw new InvalidArgumentException('no schema found to verify against');
+ }
+ }
+} \ No newline at end of file
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php
new file mode 100644
index 0000000..f57f64c
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+/**
+ * The StringConstraint Constraints, validates an string against a given schema
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
+ */
+class StringConstraint extends Constraint
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function check($element, $schema = null, $path = null, $i = null)
+ {
+ // Verify maxLength
+ if (isset($schema->maxLength) && $this->strlen($element) > $schema->maxLength) {
+ $this->addError($path, "Must be at most " . $schema->maxLength . " characters long", 'maxLength', array(
+ 'maxLength' => $schema->maxLength,
+ ));
+ }
+
+ //verify minLength
+ if (isset($schema->minLength) && $this->strlen($element) < $schema->minLength) {
+ $this->addError($path, "Must be at least " . $schema->minLength . " characters long", 'minLength', array(
+ 'minLength' => $schema->minLength,
+ ));
+ }
+
+ // Verify a regex pattern
+ if (isset($schema->pattern) && !preg_match('#' . str_replace('#', '\\#', $schema->pattern) . '#', $element)) {
+ $this->addError($path, "Does not match the regex pattern " . $schema->pattern, 'pattern', array(
+ 'pattern' => $schema->pattern,
+ ));
+ }
+
+ $this->checkFormat($element, $schema, $path, $i);
+ }
+
+ private function strlen($string)
+ {
+ if (extension_loaded('mbstring')) {
+ return mb_strlen($string, mb_detect_encoding($string));
+ } else {
+ return strlen($string);
+ }
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php
new file mode 100644
index 0000000..837cfd8
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php
@@ -0,0 +1,145 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+use JsonSchema\Exception\InvalidArgumentException;
+use UnexpectedValueException as StandardUnexpectedValueException;
+
+/**
+ * The TypeConstraint Constraints, validates an element against a given type
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
+ */
+class TypeConstraint extends Constraint
+{
+ /**
+ * @var array|string[] type wordings for validation error messages
+ */
+ static $wording = array(
+ 'integer' => 'an integer',
+ 'number' => 'a number',
+ 'boolean' => 'a boolean',
+ 'object' => 'an object',
+ 'array' => 'an array',
+ 'string' => 'a string',
+ 'null' => 'a null',
+ 'any' => NULL, // validation of 'any' is always true so is not needed in message wording
+ 0 => NULL, // validation of a false-y value is always true, so not needed as well
+ );
+
+ /**
+ * {@inheritDoc}
+ */
+ public function check($value = null, $schema = null, $path = null, $i = null)
+ {
+ $type = isset($schema->type) ? $schema->type : null;
+ $isValid = true;
+
+ if (is_array($type)) {
+ // @TODO refactor
+ $validatedOneType = false;
+ $errors = array();
+ foreach ($type as $tp) {
+ $validator = new TypeConstraint($this->checkMode);
+ $subSchema = new \stdClass();
+ $subSchema->type = $tp;
+ $validator->check($value, $subSchema, $path, null);
+ $error = $validator->getErrors();
+
+ if (!count($error)) {
+ $validatedOneType = true;
+ break;
+ }
+
+ $errors = $error;
+ }
+
+ if (!$validatedOneType) {
+ $this->addErrors($errors);
+
+ return;
+ }
+ } elseif (is_object($type)) {
+ $this->checkUndefined($value, $type, $path);
+ } else {
+ $isValid = $this->validateType($value, $type);
+ }
+
+ if ($isValid === false) {
+ if (!isset(self::$wording[$type])) {
+ throw new StandardUnexpectedValueException(
+ sprintf(
+ "No wording for %s available, expected wordings are: [%s]",
+ var_export($type, true),
+ implode(', ', array_filter(self::$wording)))
+ );
+ }
+ $this->addError($path, ucwords(gettype($value)) . " value found, but " . self::$wording[$type] . " is required", 'type');
+ }
+ }
+
+ /**
+ * Verifies that a given value is of a certain type
+ *
+ * @param mixed $value Value to validate
+ * @param string $type TypeConstraint to check against
+ *
+ * @return boolean
+ *
+ * @throws InvalidArgumentException
+ */
+ protected function validateType($value, $type)
+ {
+ //mostly the case for inline schema
+ if (!$type) {
+ return true;
+ }
+
+ if ('integer' === $type) {
+ return is_int($value);
+ }
+
+ if ('number' === $type) {
+ return is_numeric($value) && !is_string($value);
+ }
+
+ if ('boolean' === $type) {
+ return is_bool($value);
+ }
+
+ if ('object' === $type) {
+ return is_object($value);
+ //return ($this::CHECK_MODE_TYPE_CAST == $this->checkMode) ? is_array($value) : is_object($value);
+ }
+
+ if ('array' === $type) {
+ return is_array($value);
+ }
+
+ if ('string' === $type) {
+ return is_string($value);
+ }
+
+ if ('email' === $type) {
+ return is_string($value);
+ }
+
+ if ('null' === $type) {
+ return is_null($value);
+ }
+
+ if ('any' === $type) {
+ return true;
+ }
+
+ throw new InvalidArgumentException((is_object($value) ? 'object' : $value) . ' is an invalid type for ' . $type);
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php
new file mode 100644
index 0000000..c033720
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php
@@ -0,0 +1,307 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Constraints;
+
+use JsonSchema\Exception\InvalidArgumentException;
+use JsonSchema\Uri\UriResolver;
+
+/**
+ * The UndefinedConstraint Constraints
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
+ */
+class UndefinedConstraint extends Constraint
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function check($value, $schema = null, $path = null, $i = null)
+ {
+ if (is_null($schema)) {
+ return;
+ }
+
+ if (!is_object($schema)) {
+ throw new InvalidArgumentException(
+ 'Given schema must be an object in ' . $path
+ . ' but is a ' . gettype($schema)
+ );
+ }
+
+ $i = is_null($i) ? "" : $i;
+ $path = $this->incrementPath($path, $i);
+
+ // check special properties
+ $this->validateCommonProperties($value, $schema, $path);
+
+ // check allOf, anyOf, and oneOf properties
+ $this->validateOfProperties($value, $schema, $path);
+
+ // check known types
+ $this->validateTypes($value, $schema, $path, $i);
+ }
+
+ /**
+ * Validates the value against the types
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param string $path
+ * @param string $i
+ */
+ public function validateTypes($value, $schema = null, $path = null, $i = null)
+ {
+ // check array
+ if (is_array($value)) {
+ $this->checkArray($value, $schema, $path, $i);
+ }
+
+ // check object
+ if (is_object($value) && (isset($schema->properties) || isset($schema->patternProperties) || isset($schema->additionalProperties))) {
+ $this->checkObject(
+ $value,
+ isset($schema->properties) ? $schema->properties : null,
+ $path,
+ isset($schema->additionalProperties) ? $schema->additionalProperties : null,
+ isset($schema->patternProperties) ? $schema->patternProperties : null
+ );
+ }
+
+ // check string
+ if (is_string($value)) {
+ $this->checkString($value, $schema, $path, $i);
+ }
+
+ // check numeric
+ if (is_numeric($value)) {
+ $this->checkNumber($value, $schema, $path, $i);
+ }
+
+ // check enum
+ if (isset($schema->enum)) {
+ $this->checkEnum($value, $schema, $path, $i);
+ }
+ }
+
+ /**
+ * Validates common properties
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param string $path
+ * @param string $i
+ */
+ protected function validateCommonProperties($value, $schema = null, $path = null, $i = "")
+ {
+ // if it extends another schema, it must pass that schema as well
+ if (isset($schema->extends)) {
+ if (is_string($schema->extends)) {
+ $schema->extends = $this->validateUri($schema, $schema->extends);
+ }
+ if (is_array($schema->extends)) {
+ foreach ($schema->extends as $extends) {
+ $this->checkUndefined($value, $extends, $path, $i);
+ }
+ } else {
+ $this->checkUndefined($value, $schema->extends, $path, $i);
+ }
+ }
+
+ // Verify required values
+ if (is_object($value)) {
+ if (!($value instanceof UndefinedConstraint) && isset($schema->required) && is_array($schema->required) ) {
+ // Draft 4 - Required is an array of strings - e.g. "required": ["foo", ...]
+ foreach ($schema->required as $required) {
+ if (!property_exists($value, $required)) {
+ $this->addError((!$path) ? $required : "$path.$required", "The property " . $required . " is required", 'required');
+ }
+ }
+ } else if (isset($schema->required) && !is_array($schema->required)) {
+ // Draft 3 - Required attribute - e.g. "foo": {"type": "string", "required": true}
+ if ( $schema->required && $value instanceof UndefinedConstraint) {
+ $this->addError($path, "Is missing and it is required", 'required');
+ }
+ }
+ }
+
+ // Verify type
+ if (!($value instanceof UndefinedConstraint)) {
+ $this->checkType($value, $schema, $path);
+ }
+
+ // Verify disallowed items
+ if (isset($schema->disallow)) {
+ $initErrors = $this->getErrors();
+
+ $typeSchema = new \stdClass();
+ $typeSchema->type = $schema->disallow;
+ $this->checkType($value, $typeSchema, $path);
+
+ // if no new errors were raised it must be a disallowed value
+ if (count($this->getErrors()) == count($initErrors)) {
+ $this->addError($path, "Disallowed value was matched", 'disallow');
+ } else {
+ $this->errors = $initErrors;
+ }
+ }
+
+ if (isset($schema->not)) {
+ $initErrors = $this->getErrors();
+ $this->checkUndefined($value, $schema->not, $path, $i);
+
+ // if no new errors were raised then the instance validated against the "not" schema
+ if (count($this->getErrors()) == count($initErrors)) {
+ $this->addError($path, "Matched a schema which it should not", 'not');
+ } else {
+ $this->errors = $initErrors;
+ }
+ }
+
+ // Verify minimum and maximum number of properties
+ if (is_object($value)) {
+ if (isset($schema->minProperties)) {
+ if (count(get_object_vars($value)) < $schema->minProperties) {
+ $this->addError($path, "Must contain a minimum of " . $schema->minProperties . " properties", 'minProperties', array('minProperties' => $schema->minProperties,));
+ }
+ }
+ if (isset($schema->maxProperties)) {
+ if (count(get_object_vars($value)) > $schema->maxProperties) {
+ $this->addError($path, "Must contain no more than " . $schema->maxProperties . " properties", 'maxProperties', array('maxProperties' => $schema->maxProperties,));
+ }
+ }
+ }
+
+ // Verify that dependencies are met
+ if (is_object($value) && isset($schema->dependencies)) {
+ $this->validateDependencies($value, $schema->dependencies, $path);
+ }
+ }
+
+ /**
+ * Validate allOf, anyOf, and oneOf properties
+ *
+ * @param mixed $value
+ * @param mixed $schema
+ * @param string $path
+ * @param string $i
+ */
+ protected function validateOfProperties($value, $schema, $path, $i = "")
+ {
+ // Verify type
+ if ($value instanceof UndefinedConstraint) {
+ return;
+ }
+
+ if (isset($schema->allOf)) {
+ $isValid = true;
+ foreach ($schema->allOf as $allOf) {
+ $initErrors = $this->getErrors();
+ $this->checkUndefined($value, $allOf, $path, $i);
+ $isValid = $isValid && (count($this->getErrors()) == count($initErrors));
+ }
+ if (!$isValid) {
+ $this->addError($path, "Failed to match all schemas", 'allOf');
+ }
+ }
+
+ if (isset($schema->anyOf)) {
+ $isValid = false;
+ $startErrors = $this->getErrors();
+ foreach ($schema->anyOf as $anyOf) {
+ $initErrors = $this->getErrors();
+ $this->checkUndefined($value, $anyOf, $path, $i);
+ if ($isValid = (count($this->getErrors()) == count($initErrors))) {
+ break;
+ }
+ }
+ if (!$isValid) {
+ $this->addError($path, "Failed to match at least one schema", 'anyOf');
+ } else {
+ $this->errors = $startErrors;
+ }
+ }
+
+ if (isset($schema->oneOf)) {
+ $allErrors = array();
+ $matchedSchemas = 0;
+ $startErrors = $this->getErrors();
+ foreach ($schema->oneOf as $oneOf) {
+ $this->errors = array();
+ $this->checkUndefined($value, $oneOf, $path, $i);
+ if (count($this->getErrors()) == 0) {
+ $matchedSchemas++;
+ }
+ $allErrors = array_merge($allErrors, array_values($this->getErrors()));
+ }
+ if ($matchedSchemas !== 1) {
+ $this->addErrors(
+ array_merge(
+ $allErrors,
+ array(array(
+ 'property' => $path,
+ 'message' => "Failed to match exactly one schema",
+ 'constraint' => 'oneOf',
+ ),),
+ $startErrors
+ )
+ );
+ } else {
+ $this->errors = $startErrors;
+ }
+ }
+ }
+
+ /**
+ * Validate dependencies
+ *
+ * @param mixed $value
+ * @param mixed $dependencies
+ * @param string $path
+ * @param string $i
+ */
+ protected function validateDependencies($value, $dependencies, $path, $i = "")
+ {
+ foreach ($dependencies as $key => $dependency) {
+ if (property_exists($value, $key)) {
+ if (is_string($dependency)) {
+ // Draft 3 string is allowed - e.g. "dependencies": {"bar": "foo"}
+ if (!property_exists($value, $dependency)) {
+ $this->addError($path, "$key depends on $dependency and $dependency is missing", 'dependencies');
+ }
+ } else if (is_array($dependency)) {
+ // Draft 4 must be an array - e.g. "dependencies": {"bar": ["foo"]}
+ foreach ($dependency as $d) {
+ if (!property_exists($value, $d)) {
+ $this->addError($path, "$key depends on $d and $d is missing", 'dependencies');
+ }
+ }
+ } else if (is_object($dependency)) {
+ // Schema - e.g. "dependencies": {"bar": {"properties": {"foo": {...}}}}
+ $this->checkUndefined($value, $dependency, $path, $i);
+ }
+ }
+ }
+ }
+
+ protected function validateUri($schema, $schemaUri = null)
+ {
+ $resolver = new UriResolver();
+ $retriever = $this->getUriRetriever();
+
+ $jsonSchema = null;
+ if ($resolver->isValid($schemaUri)) {
+ $schemaId = property_exists($schema, 'id') ? $schema->id : null;
+ $jsonSchema = $retriever->retrieve($schemaId, $schemaUri);
+ }
+
+ return $jsonSchema;
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php
new file mode 100644
index 0000000..ec702a7
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php
@@ -0,0 +1,17 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Exception;
+
+/**
+ * Wrapper for the InvalidArgumentException
+ */
+class InvalidArgumentException extends \InvalidArgumentException
+{
+} \ No newline at end of file
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.php
new file mode 100644
index 0000000..2e94677
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.php
@@ -0,0 +1,17 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Exception;
+
+/**
+ * Wrapper for the InvalidSchemaMediaType
+ */
+class InvalidSchemaMediaTypeException extends \RuntimeException
+{
+} \ No newline at end of file
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSourceUriException.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSourceUriException.php
new file mode 100644
index 0000000..37db121
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSourceUriException.php
@@ -0,0 +1,17 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Exception;
+
+/**
+ * Wrapper for the InvalidSourceUriException
+ */
+class InvalidSourceUriException extends InvalidArgumentException
+{
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php
new file mode 100644
index 0000000..2c22881
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php
@@ -0,0 +1,40 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Exception;
+
+/**
+ * Wrapper for the JsonDecodingException
+ */
+class JsonDecodingException extends \RuntimeException
+{
+ public function __construct($code = JSON_ERROR_NONE, \Exception $previous = null)
+ {
+ switch ($code) {
+ case JSON_ERROR_DEPTH:
+ $message = 'The maximum stack depth has been exceeded';
+ break;
+ case JSON_ERROR_STATE_MISMATCH:
+ $message = 'Invalid or malformed JSON';
+ break;
+ case JSON_ERROR_CTRL_CHAR:
+ $message = 'Control character error, possibly incorrectly encoded';
+ break;
+ case JSON_ERROR_UTF8:
+ $message = 'Malformed UTF-8 characters, possibly incorrectly encoded';
+ break;
+ case JSON_ERROR_SYNTAX:
+ $message = 'JSON syntax is malformed';
+ break;
+ default:
+ $message = 'Syntax error';
+ }
+ parent::__construct($message, $code, $previous);
+ }
+} \ No newline at end of file
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.php
new file mode 100644
index 0000000..87b4ac1
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.php
@@ -0,0 +1,17 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Exception;
+
+/**
+ * Wrapper for the ResourceNotFoundException
+ */
+class ResourceNotFoundException extends \RuntimeException
+{
+} \ No newline at end of file
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.php
new file mode 100644
index 0000000..6d0b094
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.php
@@ -0,0 +1,17 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Exception;
+
+/**
+ * Wrapper for the UriResolverException
+ */
+class UriResolverException extends \RuntimeException
+{
+} \ No newline at end of file
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/RefResolver.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/RefResolver.php
new file mode 100644
index 0000000..ea0fafd
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/RefResolver.php
@@ -0,0 +1,277 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema;
+
+use JsonSchema\Exception\JsonDecodingException;
+use JsonSchema\Uri\Retrievers\UriRetrieverInterface;
+use JsonSchema\Uri\UriRetriever;
+
+/**
+ * Take in an object that's a JSON schema and take care of all $ref references
+ *
+ * @author Tyler Akins <fidian@rumkin.com>
+ * @see README.md
+ */
+class RefResolver
+{
+ /**
+ * HACK to prevent too many recursive expansions.
+ * Happens e.g. when you want to validate a schema against the schema
+ * definition.
+ *
+ * @var integer
+ */
+ protected static $depth = 0;
+
+ /**
+ * maximum references depth
+ * @var integer
+ */
+ public static $maxDepth = 7;
+
+ /**
+ * @var UriRetrieverInterface
+ */
+ protected $uriRetriever = null;
+
+ /**
+ * @var object
+ */
+ protected $rootSchema = null;
+
+ /**
+ * @param UriRetriever $retriever
+ */
+ public function __construct($retriever = null)
+ {
+ $this->uriRetriever = $retriever;
+ }
+
+ /**
+ * Retrieves a given schema given a ref and a source URI
+ *
+ * @param string $ref Reference from schema
+ * @param string $sourceUri URI where original schema was located
+ * @return object Schema
+ */
+ public function fetchRef($ref, $sourceUri)
+ {
+ $retriever = $this->getUriRetriever();
+ $jsonSchema = $retriever->retrieve($ref, $sourceUri);
+ $this->resolve($jsonSchema);
+
+ return $jsonSchema;
+ }
+
+ /**
+ * Return the URI Retriever, defaulting to making a new one if one
+ * was not yet set.
+ *
+ * @return UriRetriever
+ */
+ public function getUriRetriever()
+ {
+ if (is_null($this->uriRetriever)) {
+ $this->setUriRetriever(new UriRetriever);
+ }
+
+ return $this->uriRetriever;
+ }
+
+ /**
+ * Resolves all $ref references for a given schema. Recurses through
+ * the object to resolve references of any child schemas.
+ *
+ * The 'format' property is omitted because it isn't required for
+ * validation. Theoretically, this class could be extended to look
+ * for URIs in formats: "These custom formats MAY be expressed as
+ * an URI, and this URI MAY reference a schema of that format."
+ *
+ * The 'id' property is not filled in, but that could be made to happen.
+ *
+ * @param object $schema JSON Schema to flesh out
+ * @param string $sourceUri URI where this schema was located
+ */
+ public function resolve($schema, $sourceUri = null)
+ {
+ if (self::$depth > self::$maxDepth) {
+ self::$depth = 0;
+ throw new JsonDecodingException(JSON_ERROR_DEPTH);
+ }
+ ++self::$depth;
+
+ if (! is_object($schema)) {
+ --self::$depth;
+ return;
+ }
+
+ if (null === $sourceUri && ! empty($schema->id)) {
+ $sourceUri = $schema->id;
+ }
+
+ if (null === $this->rootSchema) {
+ $this->rootSchema = $schema;
+ }
+
+ // Resolve $ref first
+ $this->resolveRef($schema, $sourceUri);
+
+ // These properties are just schemas
+ // eg. items can be a schema or an array of schemas
+ foreach (array('additionalItems', 'additionalProperties', 'extends', 'items') as $propertyName) {
+ $this->resolveProperty($schema, $propertyName, $sourceUri);
+ }
+
+ // These are all potentially arrays that contain schema objects
+ // eg. type can be a value or an array of values/schemas
+ // eg. items can be a schema or an array of schemas
+ foreach (array('disallow', 'extends', 'items', 'type', 'allOf', 'anyOf', 'oneOf') as $propertyName) {
+ $this->resolveArrayOfSchemas($schema, $propertyName, $sourceUri);
+ }
+
+ // These are all objects containing properties whose values are schemas
+ foreach (array('dependencies', 'patternProperties', 'properties') as $propertyName) {
+ $this->resolveObjectOfSchemas($schema, $propertyName, $sourceUri);
+ }
+
+ --self::$depth;
+ }
+
+ /**
+ * Given an object and a property name, that property should be an
+ * array whose values can be schemas.
+ *
+ * @param object $schema JSON Schema to flesh out
+ * @param string $propertyName Property to work on
+ * @param string $sourceUri URI where this schema was located
+ */
+ public function resolveArrayOfSchemas($schema, $propertyName, $sourceUri)
+ {
+ if (! isset($schema->$propertyName) || ! is_array($schema->$propertyName)) {
+ return;
+ }
+
+ foreach ($schema->$propertyName as $possiblySchema) {
+ $this->resolve($possiblySchema, $sourceUri);
+ }
+ }
+
+ /**
+ * Given an object and a property name, that property should be an
+ * object whose properties are schema objects.
+ *
+ * @param object $schema JSON Schema to flesh out
+ * @param string $propertyName Property to work on
+ * @param string $sourceUri URI where this schema was located
+ */
+ public function resolveObjectOfSchemas($schema, $propertyName, $sourceUri)
+ {
+ if (! isset($schema->$propertyName) || ! is_object($schema->$propertyName)) {
+ return;
+ }
+
+ foreach (get_object_vars($schema->$propertyName) as $possiblySchema) {
+ $this->resolve($possiblySchema, $sourceUri);
+ }
+ }
+
+ /**
+ * Given an object and a property name, that property should be a
+ * schema object.
+ *
+ * @param object $schema JSON Schema to flesh out
+ * @param string $propertyName Property to work on
+ * @param string $sourceUri URI where this schema was located
+ */
+ public function resolveProperty($schema, $propertyName, $sourceUri)
+ {
+ if (! isset($schema->$propertyName)) {
+ return;
+ }
+
+ $this->resolve($schema->$propertyName, $sourceUri);
+ }
+
+ /**
+ * Look for the $ref property in the object. If found, remove the
+ * reference and augment this object with the contents of another
+ * schema.
+ *
+ * @param object $schema JSON Schema to flesh out
+ * @param string $sourceUri URI where this schema was located
+ */
+ public function resolveRef($schema, $sourceUri)
+ {
+ $ref = '$ref';
+
+ if (empty($schema->$ref)) {
+ return;
+ }
+
+ $splitRef = explode('#', $schema->$ref, 2);
+
+ $refDoc = $splitRef[0];
+ $refPath = null;
+ if (count($splitRef) === 2) {
+ $refPath = explode('/', $splitRef[1]);
+ array_shift($refPath);
+ }
+
+ if (empty($refDoc) && empty($refPath)) {
+ // TODO: Not yet implemented - root pointer ref, causes recursion issues
+ return;
+ }
+
+ if (!empty($refDoc)) {
+ $refSchema = $this->fetchRef($refDoc, $sourceUri);
+ } else {
+ $refSchema = $this->rootSchema;
+ }
+
+ if (null !== $refPath) {
+ $refSchema = $this->resolveRefSegment($refSchema, $refPath);
+ }
+
+ unset($schema->$ref);
+
+ // Augment the current $schema object with properties fetched
+ foreach (get_object_vars($refSchema) as $prop => $value) {
+ $schema->$prop = $value;
+ }
+ }
+
+ /**
+ * Set URI Retriever for use with the Ref Resolver
+ *
+ * @param UriRetriever $retriever
+ * @return $this for chaining
+ */
+ public function setUriRetriever(UriRetriever $retriever)
+ {
+ $this->uriRetriever = $retriever;
+
+ return $this;
+ }
+
+ protected function resolveRefSegment($data, $pathParts)
+ {
+ foreach ($pathParts as $path) {
+ $path = strtr($path, array('~1' => '/', '~0' => '~', '%25' => '%'));
+
+ if (is_array($data)) {
+ $data = $data[$path];
+ } else {
+ $data = $data->{$path};
+ }
+ }
+
+ return $data;
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/AbstractRetriever.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/AbstractRetriever.php
new file mode 100644
index 0000000..f924ad8
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/AbstractRetriever.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * JsonSchema
+ * @filesource
+ */
+namespace JsonSchema\Uri\Retrievers;
+
+/**
+ * AbstractRetriever implements the default shared behavior
+ * that all decendant Retrievers should inherit
+ * @author Steven Garcia <webwhammy@gmail.com>
+ */
+abstract class AbstractRetriever implements UriRetrieverInterface
+{
+ /**
+ * Media content type
+ * @var string
+ */
+ protected $contentType;
+
+ /**
+ * {@inheritDoc}
+ * @see \JsonSchema\Uri\Retrievers\UriRetrieverInterface::getContentType()
+ */
+ public function getContentType()
+ {
+ return $this->contentType;
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/Curl.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/Curl.php
new file mode 100644
index 0000000..cd8414f
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/Curl.php
@@ -0,0 +1,79 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Uri\Retrievers;
+
+use JsonSchema\Validator;
+
+/**
+ * Tries to retrieve JSON schemas from a URI using cURL library
+ *
+ * @author Sander Coolen <sander@jibber.nl>
+ */
+class Curl extends AbstractRetriever
+{
+ protected $messageBody;
+
+ public function __construct()
+ {
+ if (!function_exists('curl_init')) {
+ throw new \RuntimeException("cURL not installed");
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see \JsonSchema\Uri\Retrievers\UriRetrieverInterface::retrieve()
+ */
+ public function retrieve($uri)
+ {
+ $ch = curl_init();
+
+ curl_setopt($ch, CURLOPT_URL, $uri);
+ curl_setopt($ch, CURLOPT_HEADER, true);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: ' . Validator::SCHEMA_MEDIA_TYPE));
+
+ $response = curl_exec($ch);
+ if (false === $response) {
+ throw new \JsonSchema\Exception\ResourceNotFoundException('JSON schema not found');
+ }
+
+ $this->fetchMessageBody($response);
+ $this->fetchContentType($response);
+
+ curl_close($ch);
+
+ return $this->messageBody;
+ }
+
+ /**
+ * @param string $response cURL HTTP response
+ */
+ private function fetchMessageBody($response)
+ {
+ preg_match("/(?:\r\n){2}(.*)$/ms", $response, $match);
+ $this->messageBody = $match[1];
+ }
+
+ /**
+ * @param string $response cURL HTTP response
+ * @return boolean Whether the Content-Type header was found or not
+ */
+ protected function fetchContentType($response)
+ {
+ if (0 < preg_match("/Content-Type:(\V*)/ims", $response, $match)) {
+ $this->contentType = trim($match[1]);
+
+ return true;
+ }
+
+ return false;
+ }
+} \ No newline at end of file
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php
new file mode 100644
index 0000000..bc43de6
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php
@@ -0,0 +1,87 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Uri\Retrievers;
+
+use JsonSchema\Exception\ResourceNotFoundException;
+use JsonSchema\Validator;
+
+/**
+ * Tries to retrieve JSON schemas from a URI using file_get_contents()
+ *
+ * @author Sander Coolen <sander@jibber.nl>
+ */
+class FileGetContents extends AbstractRetriever
+{
+ protected $messageBody;
+
+ /**
+ * {@inheritDoc}
+ * @see \JsonSchema\Uri\Retrievers\UriRetrieverInterface::retrieve()
+ */
+ public function retrieve($uri)
+ {
+ $context = stream_context_create(array(
+ 'http' => array(
+ 'method' => 'GET',
+ 'header' => "Accept: " . Validator::SCHEMA_MEDIA_TYPE
+ )));
+
+ set_error_handler(function() use ($uri) {
+ throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
+ });
+ $response = file_get_contents($uri);
+ restore_error_handler();
+
+ if (false === $response) {
+ throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
+ }
+ if ($response == ''
+ && substr($uri, 0, 7) == 'file://' && substr($uri, -1) == '/'
+ ) {
+ throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
+ }
+
+ $this->messageBody = $response;
+ if (! empty($http_response_header)) {
+ $this->fetchContentType($http_response_header);
+ } else {
+ // Could be a "file://" url or something else - fake up the response
+ $this->contentType = null;
+ }
+
+ return $this->messageBody;
+ }
+
+ /**
+ * @param array $headers HTTP Response Headers
+ * @return boolean Whether the Content-Type header was found or not
+ */
+ private function fetchContentType(array $headers)
+ {
+ foreach ($headers as $header) {
+ if ($this->contentType = self::getContentTypeMatchInHeader($header)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * @param string $header
+ * @return string|null
+ */
+ protected static function getContentTypeMatchInHeader($header)
+ {
+ if (0 < preg_match("/Content-Type:(\V*)/ims", $header, $match)) {
+ return trim($match[1]);
+ }
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/PredefinedArray.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/PredefinedArray.php
new file mode 100644
index 0000000..7652c42
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/PredefinedArray.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace JsonSchema\Uri\Retrievers;
+
+use JsonSchema\Validator;
+
+/**
+ * URI retrieved based on a predefined array of schemas
+ *
+ * @example
+ *
+ * $retriever = new PredefinedArray(array(
+ * 'http://acme.com/schemas/person#' => '{ ... }',
+ * 'http://acme.com/schemas/address#' => '{ ... }',
+ * ))
+ *
+ * $schema = $retriever->retrieve('http://acme.com/schemas/person#');
+ */
+class PredefinedArray extends AbstractRetriever
+{
+ /**
+ * Contains schemas as URI => JSON
+ * @var array
+ */
+ private $schemas;
+
+ /**
+ * Constructor
+ *
+ * @param array $schemas
+ * @param string $contentType
+ */
+ public function __construct(array $schemas, $contentType = Validator::SCHEMA_MEDIA_TYPE)
+ {
+ $this->schemas = $schemas;
+ $this->contentType = $contentType;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see \JsonSchema\Uri\Retrievers\UriRetrieverInterface::retrieve()
+ */
+ public function retrieve($uri)
+ {
+ if (!array_key_exists($uri, $this->schemas)) {
+ throw new \JsonSchema\Exception\ResourceNotFoundException(sprintf(
+ 'The JSON schema "%s" was not found.',
+ $uri
+ ));
+ }
+
+ return $this->schemas[$uri];
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/UriRetrieverInterface.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/UriRetrieverInterface.php
new file mode 100644
index 0000000..c324998
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/UriRetrieverInterface.php
@@ -0,0 +1,32 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Uri\Retrievers;
+
+/**
+ * Interface for URI retrievers
+ *
+ * @author Sander Coolen <sander@jibber.nl>
+ */
+interface UriRetrieverInterface
+{
+ /**
+ * Retrieve a schema from the specified URI
+ * @param string $uri URI that resolves to a JSON schema
+ * @throws \JsonSchema\Exception\ResourceNotFoundException
+ * @return mixed string|null
+ */
+ public function retrieve($uri);
+
+ /**
+ * Get media content type
+ * @return string
+ */
+ public function getContentType();
+} \ No newline at end of file
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php
new file mode 100644
index 0000000..9784114
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php
@@ -0,0 +1,157 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Uri;
+
+use JsonSchema\Exception\UriResolverException;
+
+/**
+ * Resolves JSON Schema URIs
+ *
+ * @author Sander Coolen <sander@jibber.nl>
+ */
+class UriResolver
+{
+ /**
+ * Parses a URI into five main components
+ *
+ * @param string $uri
+ * @return array
+ */
+ public function parse($uri)
+ {
+ preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
+
+ $components = array();
+ if (5 < count($match)) {
+ $components = array(
+ 'scheme' => $match[2],
+ 'authority' => $match[4],
+ 'path' => $match[5]
+ );
+ }
+ if (7 < count($match)) {
+ $components['query'] = $match[7];
+ }
+ if (9 < count($match)) {
+ $components['fragment'] = $match[9];
+ }
+
+ return $components;
+ }
+
+ /**
+ * Builds a URI based on n array with the main components
+ *
+ * @param array $components
+ * @return string
+ */
+ public function generate(array $components)
+ {
+ $uri = $components['scheme'] . '://'
+ . $components['authority']
+ . $components['path'];
+
+ if (array_key_exists('query', $components)) {
+ $uri .= $components['query'];
+ }
+ if (array_key_exists('fragment', $components)) {
+ $uri .= '#' . $components['fragment'];
+ }
+
+ return $uri;
+ }
+
+ /**
+ * Resolves a URI
+ *
+ * @param string $uri Absolute or relative
+ * @param string $baseUri Optional base URI
+ * @return string Absolute URI
+ */
+ public function resolve($uri, $baseUri = null)
+ {
+ if ($uri == '') {
+ return $baseUri;
+ }
+
+ $components = $this->parse($uri);
+ $path = $components['path'];
+
+ if (! empty($components['scheme'])) {
+ return $uri;
+ }
+ $baseComponents = $this->parse($baseUri);
+ $basePath = $baseComponents['path'];
+
+ $baseComponents['path'] = self::combineRelativePathWithBasePath($path, $basePath);
+ if (isset($components['fragment'])) {
+ $baseComponents['fragment'] = $components['fragment'];
+ }
+
+ return $this->generate($baseComponents);
+ }
+
+ /**
+ * Tries to glue a relative path onto an absolute one
+ *
+ * @param string $relativePath
+ * @param string $basePath
+ * @return string Merged path
+ * @throws UriResolverException
+ */
+ public static function combineRelativePathWithBasePath($relativePath, $basePath)
+ {
+ $relativePath = self::normalizePath($relativePath);
+ if ($relativePath == '') {
+ return $basePath;
+ }
+ if ($relativePath{0} == '/') {
+ return $relativePath;
+ }
+
+ $basePathSegments = explode('/', $basePath);
+
+ preg_match('|^/?(\.\./(?:\./)*)*|', $relativePath, $match);
+ $numLevelUp = strlen($match[0]) /3 + 1;
+ if ($numLevelUp >= count($basePathSegments)) {
+ throw new UriResolverException(sprintf("Unable to resolve URI '%s' from base '%s'", $relativePath, $basePath));
+ }
+
+ $basePathSegments = array_slice($basePathSegments, 0, -$numLevelUp);
+ $path = preg_replace('|^/?(\.\./(\./)*)*|', '', $relativePath);
+
+ return implode('/', $basePathSegments) . '/' . $path;
+ }
+
+ /**
+ * Normalizes a URI path component by removing dot-slash and double slashes
+ *
+ * @param string $path
+ * @return string
+ */
+ private static function normalizePath($path)
+ {
+ $path = preg_replace('|((?<!\.)\./)*|', '', $path);
+ $path = preg_replace('|//|', '/', $path);
+
+ return $path;
+ }
+
+ /**
+ * @param string $uri
+ * @return boolean
+ */
+ public function isValid($uri)
+ {
+ $components = $this->parse($uri);
+
+ return !empty($components);
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php
new file mode 100644
index 0000000..c723cd9
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php
@@ -0,0 +1,289 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Uri;
+
+use JsonSchema\Uri\Retrievers\FileGetContents;
+use JsonSchema\Uri\Retrievers\UriRetrieverInterface;
+use JsonSchema\Validator;
+use JsonSchema\Exception\InvalidSchemaMediaTypeException;
+use JsonSchema\Exception\JsonDecodingException;
+use JsonSchema\Exception\ResourceNotFoundException;
+
+/**
+ * Retrieves JSON Schema URIs
+ *
+ * @author Tyler Akins <fidian@rumkin.com>
+ */
+class UriRetriever
+{
+ /**
+ * @var null|UriRetrieverInterface
+ */
+ protected $uriRetriever = null;
+
+ /**
+ * @var array|object[]
+ * @see loadSchema
+ */
+ private $schemaCache = array();
+
+ /**
+ * Guarantee the correct media type was encountered
+ *
+ * @param UriRetrieverInterface $uriRetriever
+ * @param string $uri
+ * @return bool|void
+ */
+ public function confirmMediaType($uriRetriever, $uri)
+ {
+ $contentType = $uriRetriever->getContentType();
+
+ if (is_null($contentType)) {
+ // Well, we didn't get an invalid one
+ return;
+ }
+
+ if (Validator::SCHEMA_MEDIA_TYPE === $contentType) {
+ return;
+ }
+
+ if (substr($uri, 0, 23) == 'http://json-schema.org/') {
+ //HACK; they deliver broken content types
+ return true;
+ }
+
+ throw new InvalidSchemaMediaTypeException(sprintf('Media type %s expected', Validator::SCHEMA_MEDIA_TYPE));
+ }
+
+ /**
+ * Get a URI Retriever
+ *
+ * If none is specified, sets a default FileGetContents retriever and
+ * returns that object.
+ *
+ * @return UriRetrieverInterface
+ */
+ public function getUriRetriever()
+ {
+ if (is_null($this->uriRetriever)) {
+ $this->setUriRetriever(new FileGetContents);
+ }
+
+ return $this->uriRetriever;
+ }
+
+ /**
+ * Resolve a schema based on pointer
+ *
+ * URIs can have a fragment at the end in the format of
+ * #/path/to/object and we are to look up the 'path' property of
+ * the first object then the 'to' and 'object' properties.
+ *
+ * @param object $jsonSchema JSON Schema contents
+ * @param string $uri JSON Schema URI
+ * @return object JSON Schema after walking down the fragment pieces
+ *
+ * @throws ResourceNotFoundException
+ */
+ public function resolvePointer($jsonSchema, $uri)
+ {
+ $resolver = new UriResolver();
+ $parsed = $resolver->parse($uri);
+ if (empty($parsed['fragment'])) {
+ return $jsonSchema;
+ }
+
+ $path = explode('/', $parsed['fragment']);
+ while ($path) {
+ $pathElement = array_shift($path);
+ if (! empty($pathElement)) {
+ $pathElement = str_replace('~1', '/', $pathElement);
+ $pathElement = str_replace('~0', '~', $pathElement);
+ if (! empty($jsonSchema->$pathElement)) {
+ $jsonSchema = $jsonSchema->$pathElement;
+ } else {
+ throw new ResourceNotFoundException(
+ 'Fragment "' . $parsed['fragment'] . '" not found'
+ . ' in ' . $uri
+ );
+ }
+
+ if (! is_object($jsonSchema)) {
+ throw new ResourceNotFoundException(
+ 'Fragment part "' . $pathElement . '" is no object '
+ . ' in ' . $uri
+ );
+ }
+ }
+ }
+
+ return $jsonSchema;
+ }
+
+ /**
+ * Retrieve a URI
+ *
+ * @param string $uri JSON Schema URI
+ * @param string|null $baseUri
+ * @return object JSON Schema contents
+ */
+ public function retrieve($uri, $baseUri = null)
+ {
+ $resolver = new UriResolver();
+ $resolvedUri = $fetchUri = $resolver->resolve($uri, $baseUri);
+
+ //fetch URL without #fragment
+ $arParts = $resolver->parse($resolvedUri);
+ if (isset($arParts['fragment'])) {
+ unset($arParts['fragment']);
+ $fetchUri = $resolver->generate($arParts);
+ }
+
+ $jsonSchema = $this->loadSchema($fetchUri);
+
+ // Use the JSON pointer if specified
+ $jsonSchema = $this->resolvePointer($jsonSchema, $resolvedUri);
+
+ if ($jsonSchema instanceof \stdClass) {
+ $jsonSchema->id = $resolvedUri;
+ }
+
+ return $jsonSchema;
+ }
+
+ /**
+ * Fetch a schema from the given URI, json-decode it and return it.
+ * Caches schema objects.
+ *
+ * @param string $fetchUri Absolute URI
+ *
+ * @return object JSON schema object
+ */
+ protected function loadSchema($fetchUri)
+ {
+ if (isset($this->schemaCache[$fetchUri])) {
+ return $this->schemaCache[$fetchUri];
+ }
+
+ $uriRetriever = $this->getUriRetriever();
+ $contents = $this->uriRetriever->retrieve($fetchUri);
+ $this->confirmMediaType($uriRetriever, $fetchUri);
+ $jsonSchema = json_decode($contents);
+
+ if (JSON_ERROR_NONE < $error = json_last_error()) {
+ throw new JsonDecodingException($error);
+ }
+
+ $this->schemaCache[$fetchUri] = $jsonSchema;
+
+ return $jsonSchema;
+ }
+
+ /**
+ * Set the URI Retriever
+ *
+ * @param UriRetrieverInterface $uriRetriever
+ * @return $this for chaining
+ */
+ public function setUriRetriever(UriRetrieverInterface $uriRetriever)
+ {
+ $this->uriRetriever = $uriRetriever;
+
+ return $this;
+ }
+
+ /**
+ * Parses a URI into five main components
+ *
+ * @param string $uri
+ * @return array
+ */
+ public function parse($uri)
+ {
+ preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
+
+ $components = array();
+ if (5 < count($match)) {
+ $components = array(
+ 'scheme' => $match[2],
+ 'authority' => $match[4],
+ 'path' => $match[5]
+ );
+ }
+
+ if (7 < count($match)) {
+ $components['query'] = $match[7];
+ }
+
+ if (9 < count($match)) {
+ $components['fragment'] = $match[9];
+ }
+
+ return $components;
+ }
+
+ /**
+ * Builds a URI based on n array with the main components
+ *
+ * @param array $components
+ * @return string
+ */
+ public function generate(array $components)
+ {
+ $uri = $components['scheme'] . '://'
+ . $components['authority']
+ . $components['path'];
+
+ if (array_key_exists('query', $components)) {
+ $uri .= $components['query'];
+ }
+
+ if (array_key_exists('fragment', $components)) {
+ $uri .= $components['fragment'];
+ }
+
+ return $uri;
+ }
+
+ /**
+ * Resolves a URI
+ *
+ * @param string $uri Absolute or relative
+ * @param string $baseUri Optional base URI
+ * @return string
+ */
+ public function resolve($uri, $baseUri = null)
+ {
+ $components = $this->parse($uri);
+ $path = $components['path'];
+
+ if ((array_key_exists('scheme', $components)) && ('http' === $components['scheme'])) {
+ return $uri;
+ }
+
+ $baseComponents = $this->parse($baseUri);
+ $basePath = $baseComponents['path'];
+
+ $baseComponents['path'] = UriResolver::combineRelativePathWithBasePath($path, $basePath);
+
+ return $this->generate($baseComponents);
+ }
+
+ /**
+ * @param string $uri
+ * @return boolean
+ */
+ public function isValid($uri)
+ {
+ $components = $this->parse($uri);
+
+ return !empty($components);
+ }
+}
diff --git a/server/vendor/justinrainbow/json-schema/src/JsonSchema/Validator.php b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Validator.php
new file mode 100644
index 0000000..14dbb60
--- /dev/null
+++ b/server/vendor/justinrainbow/json-schema/src/JsonSchema/Validator.php
@@ -0,0 +1,40 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema;
+
+use JsonSchema\Constraints\SchemaConstraint;
+use JsonSchema\Constraints\Constraint;
+
+/**
+ * A JsonSchema Constraint
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
+ * @see README.md
+ */
+class Validator extends Constraint
+{
+ const SCHEMA_MEDIA_TYPE = 'application/schema+json';
+
+ /**
+ * Validates the given data against the schema and returns an object containing the results
+ * Both the php object and the schema are supposed to be a result of a json_decode call.
+ * The validation works as defined by the schema proposal in http://json-schema.org
+ *
+ * {@inheritDoc}
+ */
+ public function check($value, $schema = null, $path = null, $i = null)
+ {
+ $validator = $this->getFactory()->createInstanceFor('schema');
+ $validator->check($value, $schema);
+
+ $this->addErrors(array_unique($validator->getErrors(), SORT_REGULAR));
+ }
+}
diff --git a/server/vendor/php-opencloud/openstack b/server/vendor/php-opencloud/openstack
new file mode 160000
+Subproject 8a6ec703597f0440e558d8f1f21b2ff303117db
diff --git a/server/vendor/psr/http-message/LICENSE b/server/vendor/psr/http-message/LICENSE
new file mode 100644
index 0000000..c2d8e45
--- /dev/null
+++ b/server/vendor/psr/http-message/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2014 PHP Framework Interoperability Group
+
+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/server/vendor/psr/http-message/README.md b/server/vendor/psr/http-message/README.md
new file mode 100644
index 0000000..2818533
--- /dev/null
+++ b/server/vendor/psr/http-message/README.md
@@ -0,0 +1,13 @@
+PSR Http Message
+================
+
+This repository holds all interfaces/classes/traits related to
+[PSR-7](http://www.php-fig.org/psr/psr-7/).
+
+Note that this is not a HTTP message implementation of its own. It is merely an
+interface that describes a HTTP message. See the specification for more details.
+
+Usage
+-----
+
+We'll certainly need some stuff in here. \ No newline at end of file
diff --git a/server/vendor/psr/http-message/composer.json b/server/vendor/psr/http-message/composer.json
new file mode 100644
index 0000000..4774b61
--- /dev/null
+++ b/server/vendor/psr/http-message/composer.json
@@ -0,0 +1,25 @@
+{
+ "name": "psr/http-message",
+ "description": "Common interface for HTTP messages",
+ "keywords": ["psr", "psr-7", "http", "http-message", "request", "response"],
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ }
+}
diff --git a/server/vendor/psr/http-message/src/MessageInterface.php b/server/vendor/psr/http-message/src/MessageInterface.php
new file mode 100644
index 0000000..8f67a05
--- /dev/null
+++ b/server/vendor/psr/http-message/src/MessageInterface.php
@@ -0,0 +1,187 @@
+<?php
+
+namespace Psr\Http\Message;
+
+/**
+ * HTTP messages consist of requests from a client to a server and responses
+ * from a server to a client. This interface defines the methods common to
+ * each.
+ *
+ * Messages are considered immutable; all methods that might change state MUST
+ * be implemented such that they retain the internal state of the current
+ * message and return an instance that contains the changed state.
+ *
+ * @link http://www.ietf.org/rfc/rfc7230.txt
+ * @link http://www.ietf.org/rfc/rfc7231.txt
+ */
+interface MessageInterface
+{
+ /**
+ * Retrieves the HTTP protocol version as a string.
+ *
+ * The string MUST contain only the HTTP version number (e.g., "1.1", "1.0").
+ *
+ * @return string HTTP protocol version.
+ */
+ public function getProtocolVersion();
+
+ /**
+ * Return an instance with the specified HTTP protocol version.
+ *
+ * The version string MUST contain only the HTTP version number (e.g.,
+ * "1.1", "1.0").
+ *
+ * This method MUST be implemented in such a way as to retain the
+ * immutability of the message, and MUST return an instance that has the
+ * new protocol version.
+ *
+ * @param string $version HTTP protocol version
+ * @return self
+ */
+ public function withProtocolVersion($version);
+
+ /**
+ * Retrieves all message header values.
+ *
+ * The keys represent the header name as it will be sent over the wire, and
+ * each value is an array of strings associated with the header.
+ *
+ * // Represent the headers as a string
+ * foreach ($message->getHeaders() as $name => $values) {
+ * echo $name . ": " . implode(", ", $values);
+ * }
+ *
+ * // Emit headers iteratively:
+ * foreach ($message->getHeaders() as $name => $values) {
+ * foreach ($values as $value) {
+ * header(sprintf('%s: %s', $name, $value), false);
+ * }
+ * }
+ *
+ * While header names are not case-sensitive, getHeaders() will preserve the
+ * exact case in which headers were originally specified.
+ *
+ * @return array Returns an associative array of the message's headers. Each
+ * key MUST be a header name, and each value MUST be an array of strings
+ * for that header.
+ */
+ public function getHeaders();
+
+ /**
+ * Checks if a header exists by the given case-insensitive name.
+ *
+ * @param string $name Case-insensitive header field name.
+ * @return bool Returns true if any header names match the given header
+ * name using a case-insensitive string comparison. Returns false if
+ * no matching header name is found in the message.
+ */
+ public function hasHeader($name);
+
+ /**
+ * Retrieves a message header value by the given case-insensitive name.
+ *
+ * This method returns an array of all the header values of the given
+ * case-insensitive header name.
+ *
+ * If the header does not appear in the message, this method MUST return an
+ * empty array.
+ *
+ * @param string $name Case-insensitive header field name.
+ * @return string[] An array of string values as provided for the given
+ * header. If the header does not appear in the message, this method MUST
+ * return an empty array.
+ */
+ public function getHeader($name);
+
+ /**
+ * Retrieves a comma-separated string of the values for a single header.
+ *
+ * This method returns all of the header values of the given
+ * case-insensitive header name as a string concatenated together using
+ * a comma.
+ *
+ * NOTE: Not all header values may be appropriately represented using
+ * comma concatenation. For such headers, use getHeader() instead
+ * and supply your own delimiter when concatenating.
+ *
+ * If the header does not appear in the message, this method MUST return
+ * an empty string.
+ *
+ * @param string $name Case-insensitive header field name.
+ * @return string A string of values as provided for the given header
+ * concatenated together using a comma. If the header does not appear in
+ * the message, this method MUST return an empty string.
+ */
+ public function getHeaderLine($name);
+
+ /**
+ * Return an instance with the provided value replacing the specified header.
+ *
+ * While header names are case-insensitive, the casing of the header will
+ * be preserved by this function, and returned from getHeaders().
+ *
+ * This method MUST be implemented in such a way as to retain the
+ * immutability of the message, and MUST return an instance that has the
+ * new and/or updated header and value.
+ *
+ * @param string $name Case-insensitive header field name.
+ * @param string|string[] $value Header value(s).
+ * @return self
+ * @throws \InvalidArgumentException for invalid header names or values.
+ */
+ public function withHeader($name, $value);
+
+ /**
+ * Return an instance with the specified header appended with the given value.
+ *
+ * Existing values for the specified header will be maintained. The new
+ * value(s) will be appended to the existing list. If the header did not
+ * exist previously, it will be added.
+ *
+ * This method MUST be implemented in such a way as to retain the
+ * immutability of the message, and MUST return an instance that has the
+ * new header and/or value.
+ *
+ * @param string $name Case-insensitive header field name to add.
+ * @param string|string[] $value Header value(s).
+ * @return self
+ * @throws \InvalidArgumentException for invalid header names or values.
+ */
+ public function withAddedHeader($name, $value);
+
+ /**
+ * Return an instance without the specified header.
+ *
+ * Header resolution MUST be done without case-sensitivity.
+ *
+ * This method MUST be implemented in such a way as to retain the
+ * immutability of the message, and MUST return an instance that removes
+ * the named header.
+ *
+ * @param string $name Case-insensitive header field name to remove.
+ * @return self
+ */
+ public function withoutHeader($name);
+
+ /**
+ * Gets the body of the message.
+ *
+ * @return StreamInterface Returns the body as a stream.
+ */
+ public function getBody();
+
+ /**
+ * Return an instance with the specified message body.
+ *
+ * The body MUST be a StreamInterface object.
+ *
+ * This method MUST be implemented in such a way as to retain the
+ * immutability of the message, and MUST return a new instance that has the
+ * new body stream.
+ *
+ * @param StreamInterface $body Body.
+ * @return self
+ * @throws \InvalidArgumentException When the body is not valid.
+ */
+ public function withBody(StreamInterface $body);
+}
diff --git a/server/vendor/psr/http-message/src/RequestInterface.php b/server/vendor/psr/http-message/src/RequestInterface.php
new file mode 100644
index 0000000..75c802e
--- /dev/null
+++ b/server/vendor/psr/http-message/src/RequestInterface.php
@@ -0,0 +1,129 @@
+<?php
+
+namespace Psr\Http\Message;
+
+/**
+ * Representation of an outgoing, client-side request.
+ *
+ * Per the HTTP specification, this interface includes properties for
+ * each of the following:
+ *
+ * - Protocol version
+ * - HTTP method
+ * - URI
+ * - Headers
+ * - Message body
+ *
+ * During construction, implementations MUST attempt to set the Host header from
+ * a provided URI if no Host header is provided.
+ *
+ * Requests are considered immutable; all methods that might change state MUST
+ * be implemented such that they retain the internal state of the current
+ * message and return an instance that contains the changed state.
+ */
+interface RequestInterface extends MessageInterface
+{
+ /**
+ * Retrieves the message's request target.
+ *
+ * Retrieves the message's request-target either as it will appear (for
+ * clients), as it appeared at request (for servers), or as it was
+ * specified for the instance (see withRequestTarget()).
+ *
+ * In most cases, this will be the origin-form of the composed URI,
+ * unless a value was provided to the concrete implementation (see
+ * withRequestTarget() below).
+ *
+ * If no URI is available, and no request-target has been specifically
+ * provided, this method MUST return the string "/".
+ *
+ * @return string
+ */
+ public function getRequestTarget();
+
+ /**
+ * Return an instance with the specific request-target.
+ *
+ * If the request needs a non-origin-form request-target — e.g., for
+ * specifying an absolute-form, authority-form, or asterisk-form —
+ * this method may be used to create an instance with the specified
+ * request-target, verbatim.
+ *
+ * This method MUST be implemented in such a way as to retain the
+ * immutability of the message, and MUST return an instance that has the
+ * changed request target.
+ *
+ * @link http://tools.ietf.org/html/rfc7230#section-2.7 (for the various
+ * request-target forms allowed in request messages)
+ * @param mixed $requestTarget
+ * @return self
+ */
+ public function withRequestTarget($requestTarget);
+
+ /**
+ * Retrieves the HTTP method of the request.
+ *
+ * @return string Returns the request method.
+ */
+ public function getMethod();
+
+ /**
+ * Return an instance with the provided HTTP method.
+ *
+ * While HTTP method names are typically all uppercase characters, HTTP
+ * method names are case-sensitive and thus implementations SHOULD NOT
+ * modify the given string.
+ *
+ * This method MUST be implemented in such a way as to retain the
+ * immutability of the message, and MUST return an instance that has the
+ * changed request method.
+ *
+ * @param string $method Case-sensitive method.
+ * @return self
+ * @throws \InvalidArgumentException for invalid HTTP methods.
+ */
+ public function withMethod($method);
+
+ /**
+ * Retrieves the URI instance.
+ *
+ * This method MUST return a UriInterface instance.
+ *
+ * @link http://tools.ietf.org/html/rfc3986#section-4.3
+ * @return UriInterface Returns a UriInterface instance
+ * representing the URI of the request.
+ */
+ public function getUri();
+
+ /**
+ * Returns an instance with the provided URI.
+ *
+ * This method MUST update the Host header of the returned request by
+ * default if the URI contains a host component. If the URI does not
+ * contain a host component, any pre-existing Host header MUST be carried
+ * over to the returned request.
+ *
+ * You can opt-in to preserving the original state of the Host header by
+ * setting `$preserveHost` to `true`. When `$preserveHost` is set to
+ * `true`, this method interacts with the Host header in the following ways:
+ *
+ * - If the the Host header is missing or empty, and the new URI contains
+ * a host component, this method MUST update the Host header in the returned
+ * request.
+ * - If the Host header is missing or empty, and the new URI does not contain a
+ * host component, this method MUST NOT update the Host header in the returned
+ * request.
+ * - If a Host header is present and non-empty, this method MUST NOT update
+ * the Host header in the returned request.
+ *
+ * This method MUST be implemented in such a way as to retain the
+ * immutability of the message, and MUST return an instance that has the
+ * new UriInterface instance.
+ *
+ * @link http://tools.ietf.org/html/rfc3986#section-4.3
+ * @param UriInterface $uri New request URI to use.
+ * @param bool $preserveHost Preserve the original state of the Host header.
+ * @return self
+ */
+ public function withUri(UriInterface $uri, $preserveHost = false);
+}
diff --git a/server/vendor/psr/http-message/src/ResponseInterface.php b/server/vendor/psr/http-message/src/ResponseInterface.php
new file mode 100644
index 0000000..6724809
--- /dev/null
+++ b/server/vendor/psr/http-message/src/ResponseInterface.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace Psr\Http\Message;
+
+/**
+ * Representation of an outgoing, server-side response.
+ *
+ * Per the HTTP specification, this interface includes properties for
+ * each of the following:
+ *
+ * - Protocol version
+ * - Status code and reason phrase
+ * - Headers
+ * - Message body
+ *
+ * Responses are considered immutable; all methods that might change state MUST
+ * be implemented such that they retain the internal state of the current
+ * message and return an instance that contains the changed state.
+ */
+interface ResponseInterface extends MessageInterface
+{
+ /**
+ * Gets the response status code.
+ *
+ * The status code is a 3-digit integer result code of the server's attempt
+ * to understand and satisfy the request.
+ *
+ * @return int Status code.
+ */
+ public function getStatusCode();
+
+ /**
+ * Return an instance with the specified status code and, optionally, reason phrase.
+ *
+ * If no reason phrase is specified, implementations MAY choose to default
+ * to the RFC 7231 or IANA recommended reason phrase for the response's
+ * status code.
+ *
+ * This method MUST be implemented in such a way as to retain the
+ * immutability of the message, and MUST return an instance that has the
+ * updated status and reason phrase.
+ *
+ * @link http://tools.ietf.org/html/rfc7231#section-6
+ * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
+ * @param int $code The 3-digit integer result code to set.
+ * @param string $reasonPhrase The reason phrase to use with the
+ * provided status code; if none is provided, implementations MAY
+ * use the defaults as suggested in the HTTP specification.
+ * @return self
+ * @throws \InvalidArgumentException For invalid status code arguments.
+ */
+ public function withStatus($code, $reasonPhrase = '');
+
+ /**
+ * Gets the response reason phrase associated with the status code.
+ *
+ * Because a reason phrase is not a required element in a response
+ * status line, the reason phrase value MAY be null. Implementations MAY
+ * choose to return the default RFC 7231 recommended reason phrase (or those
+ * listed in the IANA HTTP Status Code Registry) for the response's
+ * status code.
+ *
+ * @link http://tools.ietf.org/html/rfc7231#section-6
+ * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
+ * @return string Reason phrase; must return an empty string if none present.
+ */
+ public function getReasonPhrase();
+}
diff --git a/server/vendor/psr/http-message/src/ServerRequestInterface.php b/server/vendor/psr/http-message/src/ServerRequestInterface.php
new file mode 100644
index 0000000..916e065
--- /dev/null
+++ b/server/vendor/psr/http-message/src/ServerRequestInterface.php
@@ -0,0 +1,261 @@
+<?php
+
+namespace Psr\Http\Message;
+
+/**
+ * Representation of an incoming, server-side HTTP request.
+ *
+ * Per the HTTP specification, this interface includes properties for
+ * each of the following:
+ *
+ * - Protocol version
+ * - HTTP method
+ * - URI
+ * - Headers
+ * - Message body
+ *
+ * Additionally, it encapsulates all data as it has arrived to the
+ * application from the CGI and/or PHP environment, including:
+ *
+ * - The values represented in $_SERVER.
+ * - Any cookies provided (generally via $_COOKIE)
+ * - Query string arguments (generally via $_GET, or as parsed via parse_str())
+ * - Upload files, if any (as represented by $_FILES)
+ * - Deserialized body parameters (generally from $_POST)
+ *
+ * $_SERVER values MUST be treated as immutable, as they represent application
+ * state at the time of request; as such, no methods are provided to allow
+ * modification of those values. The other values provide such methods, as they
+ * can be restored from $_SERVER or the request body, and may need treatment
+ * during the application (e.g., body parameters may be deserialized based on
+ * content type).
+ *
+ * Additionally, this interface recognizes the utility of introspecting a
+ * request to derive and match additional parameters (e.g., via URI path
+ * matching, decrypting cookie values, deserializing non-form-encoded body
+ * content, matching authorization headers to users, etc). These parameters
+ * are stored in an "attributes" property.
+ *
+ * Requests are considered immutable; all methods that might change state MUST
+ * be implemented such that they retain the internal state of the current
+ * message and return an instance that contains the changed state.
+ */
+interface ServerRequestInterface extends RequestInterface
+{
+ /**
+ * Retrieve server parameters.
+ *
+ * Retrieves data related to the incoming request environment,
+ * typically derived from PHP's $_SERVER superglobal. The data IS NOT
+ * REQUIRED to originate from $_SERVER.
+ *
+ * @return array
+ */
+ public function getServerParams();
+
+ /**
+ * Retrieve cookies.
+ *
+ * Retrieves cookies sent by the client to the server.
+ *
+ * The data MUST be compatible with the structure of the $_COOKIE
+ * superglobal.
+ *
+ * @return array
+ */
+ public function getCookieParams();
+
+ /**
+ * Return an instance with the specified cookies.
+ *
+ * The data IS NOT REQUIRED to come from the $_COOKIE superglobal, but MUST
+ * be compatible with the structure of $_COOKIE. Typically, this data will
+ * be injected at instantiation.
+ *
+ * This method MUST NOT update the related Cookie header of the request
+ * instance, nor related values in the server params.
+ *
+ * This method MUST be implemented in such a way as to retain the
+ * immutability of the message, and MUST return an instance that has the
+ * updated cookie values.
+ *
+ * @param array $cookies Array of key/value pairs representing cookies.
+ * @return self
+ */
+ public function withCookieParams(array $cookies);
+
+ /**
+ * Retrieve query string arguments.
+ *
+ * Retrieves the deserialized query string arguments, if any.
+ *
+ * Note: the query params might not be in sync with the URI or server
+ * params. If you need to ensure you are only getting the original
+ * values, you may need to parse the query string from `getUri()->getQuery()`
+ * or from the `QUERY_STRING` server param.
+ *
+ * @return array
+ */
+ public function getQueryParams();
+
+ /**
+ * Return an instance with the specified query string arguments.
+ *
+ * These values SHOULD remain immutable over the course of the incoming
+ * request. They MAY be injected during instantiation, such as from PHP's
+ * $_GET superglobal, or MAY be derived from some other value such as the
+ * URI. In cases where the arguments are parsed from the URI, the data
+ * MUST be compatible with what PHP's parse_str() would return for
+ * purposes of how duplicate query parameters are handled, and how nested
+ * sets are handled.
+ *
+ * Setting query string arguments MUST NOT change the URI stored by the
+ * request, nor the values in the server params.
+ *
+ * This method MUST be implemented in such a way as to retain the
+ * immutability of the message, and MUST return an instance that has the
+ * updated query string arguments.
+ *
+ * @param array $query Array of query string arguments, typically from
+ * $_GET.
+ * @return self
+ */
+ public function withQueryParams(array $query);
+
+ /**
+ * Retrieve normalized file upload data.
+ *
+ * This method returns upload metadata in a normalized tree, with each leaf
+ * an instance of Psr\Http\Message\UploadedFileInterface.
+ *
+ * These values MAY be prepared from $_FILES or the message body during
+ * instantiation, or MAY be injected via withUploadedFiles().
+ *
+ * @return array An array tree of UploadedFileInterface instances; an empty
+ * array MUST be returned if no data is present.
+ */
+ public function getUploadedFiles();
+
+ /**
+ * Create a new instance with the specified uploaded files.
+ *
+ * This method MUST be implemented in such a way as to retain the
+ * immutability of the message, and MUST return an instance that has the
+ * updated body parameters.
+ *
+ * @param array An array tree of UploadedFileInterface instances.
+ * @return self
+ * @throws \InvalidArgumentException if an invalid structure is provided.
+ */
+ public function withUploadedFiles(array $uploadedFiles);
+
+ /**
+ * Retrieve any parameters provided in the request body.
+ *
+ * If the request Content-Type is either application/x-www-form-urlencoded
+ * or multipart/form-data, and the request method is POST, this method MUST
+ * return the contents of $_POST.
+ *
+ * Otherwise, this method may return any results of deserializing
+ * the request body content; as parsing returns structured content, the
+ * potential types MUST be arrays or objects only. A null value indicates
+ * the absence of body content.
+ *
+ * @return null|array|object The deserialized body parameters, if any.
+ * These will typically be an array or object.
+ */
+ public function getParsedBody();
+
+ /**
+ * Return an instance with the specified body parameters.
+ *
+ * These MAY be injected during instantiation.
+ *
+ * If the request Content-Type is either application/x-www-form-urlencoded
+ * or multipart/form-data, and the request method is POST, use this method
+ * ONLY to inject the contents of $_POST.
+ *
+ * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of
+ * deserializing the request body content. Deserialization/parsing returns
+ * structured data, and, as such, this method ONLY accepts arrays or objects,
+ * or a null value if nothing was available to parse.
+ *
+ * As an example, if content negotiation determines that the request data
+ * is a JSON payload, this method could be used to create a request
+ * instance with the deserialized parameters.
+ *
+ * This method MUST be implemented in such a way as to retain the
+ * immutability of the message, and MUST return an instance that has the
+ * updated body parameters.
+ *
+ * @param null|array|object $data The deserialized body data. This will
+ * typically be in an array or object.
+ * @return self
+ * @throws \InvalidArgumentException if an unsupported argument type is
+ * provided.
+ */
+ public function withParsedBody($data);
+
+ /**
+ * Retrieve attributes derived from the request.
+ *
+ * The request "attributes" may be used to allow injection of any
+ * parameters derived from the request: e.g., the results of path
+ * match operations; the results of decrypting cookies; the results of
+ * deserializing non-form-encoded message bodies; etc. Attributes
+ * will be application and request specific, and CAN be mutable.
+ *
+ * @return array Attributes derived from the request.
+ */
+ public function getAttributes();
+
+ /**
+ * Retrieve a single derived request attribute.
+ *
+ * Retrieves a single derived request attribute as described in
+ * getAttributes(). If the attribute has not been previously set, returns
+ * the default value as provided.
+ *
+ * This method obviates the need for a hasAttribute() method, as it allows
+ * specifying a default value to return if the attribute is not found.
+ *
+ * @see getAttributes()
+ * @param string $name The attribute name.
+ * @param mixed $default Default value to return if the attribute does not exist.
+ * @return mixed
+ */
+ public function getAttribute($name, $default = null);
+
+ /**
+ * Return an instance with the specified derived request attribute.
+ *
+ * This method allows setting a single derived request attribute as
+ * described in getAttributes().
+ *
+ * This method MUST be implemented in such a way as to retain the
+ * immutability of the message, and MUST return an instance that has the
+ * updated attribute.
+ *
+ * @see getAttributes()
+ * @param string $name The attribute name.
+ * @param mixed $value The value of the attribute.
+ * @return self
+ */
+ public function withAttribute($name, $value);
+
+ /**
+ * Return an instance that removes the specified derived request attribute.
+ *
+ * This method allows removing a single derived request attribute as
+ * described in getAttributes().
+ *
+ * This method MUST be implemented in such a way as to retain the
+ * immutability of the message, and MUST return an instance that removes
+ * the attribute.
+ *
+ * @see getAttributes()
+ * @param string $name The attribute name.
+ * @return self
+ */
+ public function withoutAttribute($name);
+}
diff --git a/server/vendor/psr/http-message/src/StreamInterface.php b/server/vendor/psr/http-message/src/StreamInterface.php
new file mode 100644
index 0000000..f68f391
--- /dev/null
+++ b/server/vendor/psr/http-message/src/StreamInterface.php
@@ -0,0 +1,158 @@
+<?php
+
+namespace Psr\Http\Message;
+
+/**
+ * Describes a data stream.
+ *
+ * Typically, an instance will wrap a PHP stream; this interface provides
+ * a wrapper around the most common operations, including serialization of
+ * the entire stream to a string.
+ */
+interface StreamInterface
+{
+ /**
+ * Reads all data from the stream into a string, from the beginning to end.
+ *
+ * This method MUST attempt to seek to the beginning of the stream before
+ * reading data and read the stream until the end is reached.
+ *
+ * Warning: This could attempt to load a large amount of data into memory.
+ *
+ * This method MUST NOT raise an exception in order to conform with PHP's
+ * string casting operations.
+ *
+ * @see http://php.net/manual/en/language.oop5.magic.php#object.tostring
+ * @return string
+ */
+ public function __toString();
+
+ /**
+ * Closes the stream and any underlying resources.
+ *
+ * @return void
+ */
+ public function close();
+
+ /**
+ * Separates any underlying resources from the stream.
+ *
+ * After the stream has been detached, the stream is in an unusable state.
+ *
+ * @return resource|null Underlying PHP stream, if any
+ */
+ public function detach();
+
+ /**
+ * Get the size of the stream if known.
+ *
+ * @return int|null Returns the size in bytes if known, or null if unknown.
+ */
+ public function getSize();
+
+ /**
+ * Returns the current position of the file read/write pointer
+ *
+ * @return int Position of the file pointer
+ * @throws \RuntimeException on error.
+ */
+ public function tell();
+
+ /**
+ * Returns true if the stream is at the end of the stream.
+ *
+ * @return bool
+ */
+ public function eof();
+
+ /**
+ * Returns whether or not the stream is seekable.
+ *
+ * @return bool
+ */
+ public function isSeekable();
+
+ /**
+ * Seek to a position in the stream.
+ *
+ * @link http://www.php.net/manual/en/function.fseek.php
+ * @param int $offset Stream offset
+ * @param int $whence Specifies how the cursor position will be calculated
+ * based on the seek offset. Valid values are identical to the built-in
+ * PHP $whence values for `fseek()`. SEEK_SET: Set position equal to
+ * offset bytes SEEK_CUR: Set position to current location plus offset
+ * SEEK_END: Set position to end-of-stream plus offset.
+ * @throws \RuntimeException on failure.
+ */
+ public function seek($offset, $whence = SEEK_SET);
+
+ /**
+ * Seek to the beginning of the stream.
+ *
+ * If the stream is not seekable, this method will raise an exception;
+ * otherwise, it will perform a seek(0).
+ *
+ * @see seek()
+ * @link http://www.php.net/manual/en/function.fseek.php
+ * @throws \RuntimeException on failure.
+ */
+ public function rewind();
+
+ /**
+ * Returns whether or not the stream is writable.
+ *
+ * @return bool
+ */
+ public function isWritable();
+
+ /**
+ * Write data to the stream.
+ *
+ * @param string $string The string that is to be written.
+ * @return int Returns the number of bytes written to the stream.
+ * @throws \RuntimeException on failure.
+ */
+ public function write($string);
+
+ /**
+ * Returns whether or not the stream is readable.
+ *
+ * @return bool
+ */
+ public function isReadable();
+
+ /**
+ * Read data from the stream.
+ *
+ * @param int $length Read up to $length bytes from the object and return
+ * them. Fewer than $length bytes may be returned if underlying stream
+ * call returns fewer bytes.
+ * @return string Returns the data read from the stream, or an empty string
+ * if no bytes are available.
+ * @throws \RuntimeException if an error occurs.
+ */
+ public function read($length);
+
+ /**
+ * Returns the remaining contents in a string
+ *
+ * @return string
+ * @throws \RuntimeException if unable to read or an error occurs while
+ * reading.
+ */
+ public function getContents();
+
+ /**
+ * Get stream metadata as an associative array or retrieve a specific key.
+ *
+ * The keys returned are identical to the keys returned from PHP's
+ * stream_get_meta_data() function.
+ *
+ * @link http://php.net/manual/en/function.stream-get-meta-data.php
+ * @param string $key Specific metadata to retrieve.
+ * @return array|mixed|null Returns an associative array if no key is
+ * provided. Returns a specific key value if a key is provided and the
+ * value is found, or null if the key is not found.
+ */
+ public function getMetadata($key = null);
+}
diff --git a/server/vendor/psr/http-message/src/UploadedFileInterface.php b/server/vendor/psr/http-message/src/UploadedFileInterface.php
new file mode 100644
index 0000000..5ad288d
--- /dev/null
+++ b/server/vendor/psr/http-message/src/UploadedFileInterface.php
@@ -0,0 +1,123 @@
+<?php
+
+namespace Psr\Http\Message;
+
+/**
+ * Value object representing a file uploaded through an HTTP request.
+ *
+ * Instances of this interface are considered immutable; all methods that
+ * might change state MUST be implemented such that they retain the internal
+ * state of the current instance and return an instance that contains the
+ * changed state.
+ */
+interface UploadedFileInterface
+{
+ /**
+ * Retrieve a stream representing the uploaded file.
+ *
+ * This method MUST return a StreamInterface instance, representing the
+ * uploaded file. The purpose of this method is to allow utilizing native PHP
+ * stream functionality to manipulate the file upload, such as
+ * stream_copy_to_stream() (though the result will need to be decorated in a
+ * native PHP stream wrapper to work with such functions).
+ *
+ * If the moveTo() method has been called previously, this method MUST raise
+ * an exception.
+ *
+ * @return StreamInterface Stream representation of the uploaded file.
+ * @throws \RuntimeException in cases when no stream is available or can be
+ * created.
+ */
+ public function getStream();
+
+ /**
+ * Move the uploaded file to a new location.
+ *
+ * Use this method as an alternative to move_uploaded_file(). This method is
+ * guaranteed to work in both SAPI and non-SAPI environments.
+ * Implementations must determine which environment they are in, and use the
+ * appropriate method (move_uploaded_file(), rename(), or a stream
+ * operation) to perform the operation.
+ *
+ * $targetPath may be an absolute path, or a relative path. If it is a
+ * relative path, resolution should be the same as used by PHP's rename()
+ * function.
+ *
+ * The original file or stream MUST be removed on completion.
+ *
+ * If this method is called more than once, any subsequent calls MUST raise
+ * an exception.
+ *
+ * When used in an SAPI environment where $_FILES is populated, when writing
+ * files via moveTo(), is_uploaded_file() and move_uploaded_file() SHOULD be
+ * used to ensure permissions and upload status are verified correctly.
+ *
+ * If you wish to move to a stream, use getStream(), as SAPI operations
+ * cannot guarantee writing to stream destinations.
+ *
+ * @see http://php.net/is_uploaded_file
+ * @see http://php.net/move_uploaded_file
+ * @param string $targetPath Path to which to move the uploaded file.
+ * @throws \InvalidArgumentException if the $path specified is invalid.
+ * @throws \RuntimeException on any error during the move operation, or on
+ * the second or subsequent call to the method.
+ */
+ public function moveTo($targetPath);
+
+ /**
+ * Retrieve the file size.
+ *
+ * Implementations SHOULD return the value stored in the "size" key of
+ * the file in the $_FILES array if available, as PHP calculates this based
+ * on the actual size transmitted.
+ *
+ * @return int|null The file size in bytes or null if unknown.
+ */
+ public function getSize();
+
+ /**
+ * Retrieve the error associated with the uploaded file.
+ *
+ * The return value MUST be one of PHP's UPLOAD_ERR_XXX constants.
+ *
+ * If the file was uploaded successfully, this method MUST return
+ * UPLOAD_ERR_OK.
+ *
+ * Implementations SHOULD return the value stored in the "error" key of
+ * the file in the $_FILES array.
+ *
+ * @see http://php.net/manual/en/features.file-upload.errors.php
+ * @return int One of PHP's UPLOAD_ERR_XXX constants.
+ */
+ public function getError();
+
+ /**
+ * Retrieve the filename sent by the client.
+ *
+ * Do not trust the value returned by this method. A client could send
+ * a malicious filename with the intention to corrupt or hack your
+ * application.
+ *
+ * Implementations SHOULD return the value stored in the "name" key of
+ * the file in the $_FILES array.
+ *
+ * @return string|null The filename sent by the client or null if none
+ * was provided.
+ */
+ public function getClientFilename();
+
+ /**
+ * Retrieve the media type sent by the client.
+ *
+ * Do not trust the value returned by this method. A client could send
+ * a malicious media type with the intention to corrupt or hack your
+ * application.
+ *
+ * Implementations SHOULD return the value stored in the "type" key of
+ * the file in the $_FILES array.
+ *
+ * @return string|null The media type sent by the client or null if none
+ * was provided.
+ */
+ public function getClientMediaType();
+}
diff --git a/server/vendor/psr/http-message/src/UriInterface.php b/server/vendor/psr/http-message/src/UriInterface.php
new file mode 100644
index 0000000..1ff5bf0
--- /dev/null
+++ b/server/vendor/psr/http-message/src/UriInterface.php
@@ -0,0 +1,323 @@
+<?php
+namespace Psr\Http\Message;
+
+/**
+ * Value object representing a URI.
+ *
+ * This interface is meant to represent URIs according to RFC 3986 and to
+ * provide methods for most common operations. Additional functionality for
+ * working with URIs can be provided on top of the interface or externally.
+ * Its primary use is for HTTP requests, but may also be used in other
+ * contexts.
+ *
+ * Instances of this interface are considered immutable; all methods that
+ * might change state MUST be implemented such that they retain the internal
+ * state of the current instance and return an instance that contains the
+ * changed state.
+ *
+ * Typically the Host header will be also be present in the request message.
+ * For server-side requests, the scheme will typically be discoverable in the
+ * server parameters.
+ *
+ * @link http://tools.ietf.org/html/rfc3986 (the URI specification)
+ */
+interface UriInterface
+{
+ /**
+ * Retrieve the scheme component of the URI.
+ *
+ * If no scheme is present, this method MUST return an empty string.
+ *
+ * The value returned MUST be normalized to lowercase, per RFC 3986
+ * Section 3.1.
+ *
+ * The trailing ":" character is not part of the scheme and MUST NOT be
+ * added.
+ *
+ * @see https://tools.ietf.org/html/rfc3986#section-3.1
+ * @return string The URI scheme.
+ */
+ public function getScheme();
+
+ /**
+ * Retrieve the authority component of the URI.
+ *
+ * If no authority information is present, this method MUST return an empty
+ * string.
+ *
+ * The authority syntax of the URI is:
+ *
+ * <pre>
+ * [user-info@]host[:port]
+ * </pre>
+ *
+ * If the port component is not set or is the standard port for the current
+ * scheme, it SHOULD NOT be included.
+ *
+ * @see https://tools.ietf.org/html/rfc3986#section-3.2
+ * @return string The URI authority, in "[user-info@]host[:port]" format.
+ */
+ public function getAuthority();
+
+ /**
+ * Retrieve the user information component of the URI.
+ *
+ * If no user information is present, this method MUST return an empty
+ * string.
+ *
+ * If a user is present in the URI, this will return that value;
+ * additionally, if the password is also present, it will be appended to the
+ * user value, with a colon (":") separating the values.
+ *
+ * The trailing "@" character is not part of the user information and MUST
+ * NOT be added.
+ *
+ * @return string The URI user information, in "username[:password]" format.
+ */
+ public function getUserInfo();
+
+ /**
+ * Retrieve the host component of the URI.
+ *
+ * If no host is present, this method MUST return an empty string.
+ *
+ * The value returned MUST be normalized to lowercase, per RFC 3986
+ * Section 3.2.2.
+ *
+ * @see http://tools.ietf.org/html/rfc3986#section-3.2.2
+ * @return string The URI host.
+ */
+ public function getHost();
+
+ /**
+ * Retrieve the port component of the URI.
+ *
+ * If a port is present, and it is non-standard for the current scheme,
+ * this method MUST return it as an integer. If the port is the standard port
+ * used with the current scheme, this method SHOULD return null.
+ *
+ * If no port is present, and no scheme is present, this method MUST return
+ * a null value.
+ *
+ * If no port is present, but a scheme is present, this method MAY return
+ * the standard port for that scheme, but SHOULD return null.
+ *
+ * @return null|int The URI port.
+ */
+ public function getPort();
+
+ /**
+ * Retrieve the path component of the URI.
+ *
+ * The path can either be empty or absolute (starting with a slash) or
+ * rootless (not starting with a slash). Implementations MUST support all
+ * three syntaxes.
+ *
+ * Normally, the empty path "" and absolute path "/" are considered equal as
+ * defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically
+ * do this normalization because in contexts with a trimmed base path, e.g.
+ * the front controller, this difference becomes significant. It's the task
+ * of the user to handle both "" and "/".
+ *
+ * The value returned MUST be percent-encoded, but MUST NOT double-encode
+ * any characters. To determine what characters to encode, please refer to
+ * RFC 3986, Sections 2 and 3.3.
+ *
+ * As an example, if the value should include a slash ("/") not intended as
+ * delimiter between path segments, that value MUST be passed in encoded
+ * form (e.g., "%2F") to the instance.
+ *
+ * @see https://tools.ietf.org/html/rfc3986#section-2
+ * @see https://tools.ietf.org/html/rfc3986#section-3.3
+ * @return string The URI path.
+ */
+ public function getPath();
+
+ /**
+ * Retrieve the query string of the URI.
+ *
+ * If no query string is present, this method MUST return an empty string.
+ *
+ * The leading "?" character is not part of the query and MUST NOT be
+ * added.
+ *
+ * The value returned MUST be percent-encoded, but MUST NOT double-encode
+ * any characters. To determine what characters to encode, please refer to
+ * RFC 3986, Sections 2 and 3.4.
+ *
+ * As an example, if a value in a key/value pair of the query string should
+ * include an ampersand ("&") not intended as a delimiter between values,
+ * that value MUST be passed in encoded form (e.g., "%26") to the instance.
+ *
+ * @see https://tools.ietf.org/html/rfc3986#section-2
+ * @see https://tools.ietf.org/html/rfc3986#section-3.4
+ * @return string The URI query string.
+ */
+ public function getQuery();
+
+ /**
+ * Retrieve the fragment component of the URI.
+ *
+ * If no fragment is present, this method MUST return an empty string.
+ *
+ * The leading "#" character is not part of the fragment and MUST NOT be
+ * added.
+ *
+ * The value returned MUST be percent-encoded, but MUST NOT double-encode
+ * any characters. To determine what characters to encode, please refer to
+ * RFC 3986, Sections 2 and 3.5.
+ *
+ * @see https://tools.ietf.org/html/rfc3986#section-2
+ * @see https://tools.ietf.org/html/rfc3986#section-3.5
+ * @return string The URI fragment.
+ */
+ public function getFragment();
+
+ /**
+ * Return an instance with the specified scheme.
+ *
+ * This method MUST retain the state of the current instance, and return
+ * an instance that contains the specified scheme.
+ *
+ * Implementations MUST support the schemes "http" and "https" case
+ * insensitively, and MAY accommodate other schemes if required.
+ *
+ * An empty scheme is equivalent to removing the scheme.
+ *
+ * @param string $scheme The scheme to use with the new instance.
+ * @return self A new instance with the specified scheme.
+ * @throws \InvalidArgumentException for invalid or unsupported schemes.
+ */
+ public function withScheme($scheme);
+
+ /**
+ * Return an instance with the specified user information.
+ *
+ * This method MUST retain the state of the current instance, and return
+ * an instance that contains the specified user information.
+ *
+ * Password is optional, but the user information MUST include the
+ * user; an empty string for the user is equivalent to removing user
+ * information.
+ *
+ * @param string $user The user name to use for authority.
+ * @param null|string $password The password associated with $user.
+ * @return self A new instance with the specified user information.
+ */
+ public function withUserInfo($user, $password = null);
+
+ /**
+ * Return an instance with the specified host.
+ *
+ * This method MUST retain the state of the current instance, and return
+ * an instance that contains the specified host.
+ *
+ * An empty host value is equivalent to removing the host.
+ *
+ * @param string $host The hostname to use with the new instance.
+ * @return self A new instance with the specified host.
+ * @throws \InvalidArgumentException for invalid hostnames.
+ */
+ public function withHost($host);
+
+ /**
+ * Return an instance with the specified port.
+ *
+ * This method MUST retain the state of the current instance, and return
+ * an instance that contains the specified port.
+ *
+ * Implementations MUST raise an exception for ports outside the
+ * established TCP and UDP port ranges.
+ *
+ * A null value provided for the port is equivalent to removing the port
+ * information.
+ *
+ * @param null|int $port The port to use with the new instance; a null value
+ * removes the port information.
+ * @return self A new instance with the specified port.
+ * @throws \InvalidArgumentException for invalid ports.
+ */
+ public function withPort($port);
+
+ /**
+ * Return an instance with the specified path.
+ *
+ * This method MUST retain the state of the current instance, and return
+ * an instance that contains the specified path.
+ *
+ * The path can either be empty or absolute (starting with a slash) or
+ * rootless (not starting with a slash). Implementations MUST support all
+ * three syntaxes.
+ *
+ * If the path is intended to be domain-relative rather than path relative then
+ * it must begin with a slash ("/"). Paths not starting with a slash ("/")
+ * are assumed to be relative to some base path known to the application or
+ * consumer.
+ *
+ * Users can provide both encoded and decoded path characters.
+ * Implementations ensure the correct encoding as outlined in getPath().
+ *
+ * @param string $path The path to use with the new instance.
+ * @return self A new instance with the specified path.
+ * @throws \InvalidArgumentException for invalid paths.
+ */
+ public function withPath($path);
+
+ /**
+ * Return an instance with the specified query string.
+ *
+ * This method MUST retain the state of the current instance, and return
+ * an instance that contains the specified query string.
+ *
+ * Users can provide both encoded and decoded query characters.
+ * Implementations ensure the correct encoding as outlined in getQuery().
+ *
+ * An empty query string value is equivalent to removing the query string.
+ *
+ * @param string $query The query string to use with the new instance.
+ * @return self A new instance with the specified query string.
+ * @throws \InvalidArgumentException for invalid query strings.
+ */
+ public function withQuery($query);
+
+ /**
+ * Return an instance with the specified URI fragment.
+ *
+ * This method MUST retain the state of the current instance, and return
+ * an instance that contains the specified URI fragment.
+ *
+ * Users can provide both encoded and decoded fragment characters.
+ * Implementations ensure the correct encoding as outlined in getFragment().
+ *
+ * An empty fragment value is equivalent to removing the fragment.
+ *
+ * @param string $fragment The fragment to use with the new instance.
+ * @return self A new instance with the specified fragment.
+ */
+ public function withFragment($fragment);
+
+ /**
+ * Return the string representation as a URI reference.
+ *
+ * Depending on which components of the URI are present, the resulting
+ * string is either a full URI or relative reference according to RFC 3986,
+ * Section 4.1. The method concatenates the various components of the URI,
+ * using the appropriate delimiters:
+ *
+ * - If a scheme is present, it MUST be suffixed by ":".
+ * - If an authority is present, it MUST be prefixed by "//".
+ * - The path can be concatenated without delimiters. But there are two
+ * cases where the path has to be adjusted to make the URI reference
+ * valid as PHP does not allow to throw an exception in __toString():
+ * - If the path is rootless and an authority is present, the path MUST
+ * be prefixed by "/".
+ * - If the path is starting with more than one "/" and no authority is
+ * present, the starting slashes MUST be reduced to one.
+ * - If a query is present, it MUST be prefixed by "?".
+ * - If a fragment is present, it MUST be prefixed by "#".
+ *
+ * @see http://tools.ietf.org/html/rfc3986#section-4.1
+ * @return string
+ */
+ public function __toString();
+}