From a44cc1d2e3c0f147e91a5c052ac7fd879e34e706 Mon Sep 17 00:00:00 2001 From: Eole Date: Thu, 21 Jan 2016 10:29:26 +0100 Subject: [PATCH] Init Server Composer Components --- server/composer.json | 5 + server/composer.lock | 351 +++++ server/composer.phar | Bin 0 -> 1514291 bytes server/vendor/autoload.php | 7 + server/vendor/bin/validate-json | 1 + server/vendor/composer/ClassLoader.php | 413 ++++++ server/vendor/composer/LICENSE | 21 + server/vendor/composer/autoload_classmap.php | 9 + server/vendor/composer/autoload_files.php | 12 + .../vendor/composer/autoload_namespaces.php | 9 + server/vendor/composer/autoload_psr4.php | 15 + server/vendor/composer/autoload_real.php | 59 + server/vendor/composer/installed.json | 344 +++++ server/vendor/guzzlehttp/guzzle/.travis.yml | 40 + server/vendor/guzzlehttp/guzzle/CHANGELOG.md | 1203 +++++++++++++++++ server/vendor/guzzlehttp/guzzle/LICENSE | 19 + server/vendor/guzzlehttp/guzzle/README.md | 90 ++ server/vendor/guzzlehttp/guzzle/UPGRADING.md | 1203 +++++++++++++++++ server/vendor/guzzlehttp/guzzle/composer.json | 41 + .../vendor/guzzlehttp/guzzle/src/Client.php | 397 ++++++ .../guzzlehttp/guzzle/src/ClientInterface.php | 84 ++ .../guzzle/src/Cookie/CookieJar.php | 277 ++++ .../guzzle/src/Cookie/CookieJarInterface.php | 84 ++ .../guzzle/src/Cookie/FileCookieJar.php | 87 ++ .../guzzle/src/Cookie/SessionCookieJar.php | 72 + .../guzzle/src/Cookie/SetCookie.php | 404 ++++++ .../src/Exception/BadResponseException.php | 7 + .../guzzle/src/Exception/ClientException.php | 7 + .../guzzle/src/Exception/ConnectException.php | 37 + .../guzzle/src/Exception/GuzzleException.php | 4 + .../guzzle/src/Exception/RequestException.php | 188 +++ .../guzzle/src/Exception/SeekException.php | 27 + .../guzzle/src/Exception/ServerException.php | 7 + .../Exception/TooManyRedirectsException.php | 4 + .../src/Exception/TransferException.php | 4 + .../guzzle/src/Handler/CurlFactory.php | 531 ++++++++ .../src/Handler/CurlFactoryInterface.php | 27 + .../guzzle/src/Handler/CurlHandler.php | 45 + .../guzzle/src/Handler/CurlMultiHandler.php | 197 +++ .../guzzle/src/Handler/EasyHandle.php | 87 ++ .../guzzle/src/Handler/MockHandler.php | 176 +++ .../guzzlehttp/guzzle/src/Handler/Proxy.php | 55 + .../guzzle/src/Handler/StreamHandler.php | 458 +++++++ .../guzzlehttp/guzzle/src/HandlerStack.php | 273 ++++ .../guzzle/src/MessageFormatter.php | 182 +++ .../guzzlehttp/guzzle/src/Middleware.php | 249 ++++ server/vendor/guzzlehttp/guzzle/src/Pool.php | 123 ++ .../guzzle/src/PrepareBodyMiddleware.php | 112 ++ .../guzzle/src/RedirectMiddleware.php | 231 ++++ .../guzzlehttp/guzzle/src/RequestOptions.php | 244 ++++ .../guzzlehttp/guzzle/src/RetryMiddleware.php | 111 ++ .../guzzlehttp/guzzle/src/TransferStats.php | 126 ++ .../guzzlehttp/guzzle/src/UriTemplate.php | 241 ++++ .../guzzlehttp/guzzle/src/functions.php | 284 ++++ .../guzzle/src/functions_include.php | 6 + server/vendor/guzzlehttp/promises/.gitignore | 11 + server/vendor/guzzlehttp/promises/.travis.yml | 19 + .../vendor/guzzlehttp/promises/CHANGELOG.md | 21 + server/vendor/guzzlehttp/promises/LICENSE | 19 + server/vendor/guzzlehttp/promises/Makefile | 13 + server/vendor/guzzlehttp/promises/README.md | 501 +++++++ .../vendor/guzzlehttp/promises/composer.json | 31 + .../guzzlehttp/promises/phpunit.xml.dist | 17 + .../promises/src/AggregateException.php | 16 + .../promises/src/CancellationException.php | 9 + .../guzzlehttp/promises/src/EachPromise.php | 207 +++ .../promises/src/FulfilledPromise.php | 80 ++ .../guzzlehttp/promises/src/Promise.php | 268 ++++ .../promises/src/PromiseInterface.php | 93 ++ .../promises/src/PromisorInterface.php | 15 + .../promises/src/RejectedPromise.php | 84 ++ .../promises/src/RejectionException.php | 47 + .../guzzlehttp/promises/src/TaskQueue.php | 79 ++ .../guzzlehttp/promises/src/functions.php | 495 +++++++ .../promises/src/functions_include.php | 6 + .../promises/tests/AggregateExceptionTest.php | 14 + .../promises/tests/EachPromiseTest.php | 294 ++++ .../promises/tests/FulfilledPromiseTest.php | 108 ++ .../promises/tests/NotPromiseInstance.php | 50 + .../guzzlehttp/promises/tests/PromiseTest.php | 579 ++++++++ .../promises/tests/RejectedPromiseTest.php | 143 ++ .../promises/tests/RejectionExceptionTest.php | 47 + .../promises/tests/TaskQueueTest.php | 31 + .../guzzlehttp/promises/tests/Thennable.php | 24 + .../guzzlehttp/promises/tests/bootstrap.php | 4 + .../promises/tests/functionsTest.php | 694 ++++++++++ server/vendor/guzzlehttp/psr7/.gitignore | 11 + server/vendor/guzzlehttp/psr7/.travis.yml | 20 + server/vendor/guzzlehttp/psr7/CHANGELOG.md | 32 + server/vendor/guzzlehttp/psr7/LICENSE | 19 + server/vendor/guzzlehttp/psr7/Makefile | 13 + server/vendor/guzzlehttp/psr7/README.md | 580 ++++++++ server/vendor/guzzlehttp/psr7/composer.json | 35 + .../vendor/guzzlehttp/psr7/phpunit.xml.dist | 17 + .../guzzlehttp/psr7/src/AppendStream.php | 233 ++++ .../guzzlehttp/psr7/src/BufferStream.php | 137 ++ .../guzzlehttp/psr7/src/CachingStream.php | 135 ++ .../guzzlehttp/psr7/src/DroppingStream.php | 42 + .../vendor/guzzlehttp/psr7/src/FnStream.php | 149 ++ .../guzzlehttp/psr7/src/InflateStream.php | 29 + .../guzzlehttp/psr7/src/LazyOpenStream.php | 39 + .../guzzlehttp/psr7/src/LimitStream.php | 155 +++ .../guzzlehttp/psr7/src/MessageTrait.php | 158 +++ .../guzzlehttp/psr7/src/MultipartStream.php | 153 +++ .../guzzlehttp/psr7/src/NoSeekStream.php | 22 + .../vendor/guzzlehttp/psr7/src/PumpStream.php | 165 +++ server/vendor/guzzlehttp/psr7/src/Request.php | 149 ++ .../vendor/guzzlehttp/psr7/src/Response.php | 130 ++ server/vendor/guzzlehttp/psr7/src/Stream.php | 245 ++++ .../psr7/src/StreamDecoratorTrait.php | 149 ++ .../guzzlehttp/psr7/src/StreamWrapper.php | 121 ++ server/vendor/guzzlehttp/psr7/src/Uri.php | 599 ++++++++ .../vendor/guzzlehttp/psr7/src/functions.php | 802 +++++++++++ .../guzzlehttp/psr7/src/functions_include.php | 6 + .../psr7/tests/AppendStreamTest.php | 186 +++ .../psr7/tests/BufferStreamTest.php | 63 + .../psr7/tests/CachingStreamTest.php | 166 +++ .../psr7/tests/DroppingStreamTest.php | 26 + .../guzzlehttp/psr7/tests/FnStreamTest.php | 90 ++ .../guzzlehttp/psr7/tests/FunctionsTest.php | 586 ++++++++ .../psr7/tests/InflateStreamTest.php | 16 + .../psr7/tests/LazyOpenStreamTest.php | 64 + .../guzzlehttp/psr7/tests/LimitStreamTest.php | 166 +++ .../psr7/tests/MultipartStreamTest.php | 214 +++ .../psr7/tests/NoSeekStreamTest.php | 40 + .../guzzlehttp/psr7/tests/PumpStreamTest.php | 72 + .../guzzlehttp/psr7/tests/RequestTest.php | 157 +++ .../guzzlehttp/psr7/tests/ResponseTest.php | 146 ++ .../psr7/tests/StreamDecoratorTraitTest.php | 137 ++ .../guzzlehttp/psr7/tests/StreamTest.php | 161 +++ .../psr7/tests/StreamWrapperTest.php | 100 ++ .../vendor/guzzlehttp/psr7/tests/UriTest.php | 247 ++++ .../guzzlehttp/psr7/tests/bootstrap.php | 11 + .../justinrainbow/json-schema/.gitattributes | 5 + .../vendor/justinrainbow/json-schema/LICENSE | 29 + .../justinrainbow/json-schema/README.md | 55 + .../json-schema/bin/validate-json | 245 ++++ .../justinrainbow/json-schema/composer.json | 58 + .../json-schema/phpunit.xml.dist | 26 + .../Constraints/CollectionConstraint.php | 112 ++ .../src/JsonSchema/Constraints/Constraint.php | 291 ++++ .../Constraints/ConstraintInterface.php | 60 + .../JsonSchema/Constraints/EnumConstraint.php | 46 + .../src/JsonSchema/Constraints/Factory.php | 81 ++ .../Constraints/FormatConstraint.php | 181 +++ .../Constraints/NumberConstraint.php | 83 ++ .../Constraints/ObjectConstraint.php | 149 ++ .../Constraints/SchemaConstraint.php | 37 + .../Constraints/StringConstraint.php | 57 + .../JsonSchema/Constraints/TypeConstraint.php | 145 ++ .../Constraints/UndefinedConstraint.php | 307 +++++ .../Exception/InvalidArgumentException.php | 17 + .../InvalidSchemaMediaTypeException.php | 17 + .../Exception/InvalidSourceUriException.php | 17 + .../Exception/JsonDecodingException.php | 40 + .../Exception/ResourceNotFoundException.php | 17 + .../Exception/UriResolverException.php | 17 + .../src/JsonSchema/RefResolver.php | 277 ++++ .../Uri/Retrievers/AbstractRetriever.php | 29 + .../src/JsonSchema/Uri/Retrievers/Curl.php | 79 ++ .../Uri/Retrievers/FileGetContents.php | 87 ++ .../Uri/Retrievers/PredefinedArray.php | 54 + .../Uri/Retrievers/UriRetrieverInterface.php | 32 + .../src/JsonSchema/Uri/UriResolver.php | 157 +++ .../src/JsonSchema/Uri/UriRetriever.php | 289 ++++ .../json-schema/src/JsonSchema/Validator.php | 40 + server/vendor/php-opencloud/openstack | 1 + server/vendor/psr/http-message/LICENSE | 19 + server/vendor/psr/http-message/README.md | 13 + server/vendor/psr/http-message/composer.json | 25 + .../psr/http-message/src/MessageInterface.php | 187 +++ .../psr/http-message/src/RequestInterface.php | 129 ++ .../http-message/src/ResponseInterface.php | 68 + .../src/ServerRequestInterface.php | 261 ++++ .../psr/http-message/src/StreamInterface.php | 158 +++ .../src/UploadedFileInterface.php | 123 ++ .../psr/http-message/src/UriInterface.php | 323 +++++ 177 files changed, 24745 insertions(+) create mode 100644 server/composer.json create mode 100644 server/composer.lock create mode 100755 server/composer.phar create mode 100644 server/vendor/autoload.php create mode 120000 server/vendor/bin/validate-json create mode 100644 server/vendor/composer/ClassLoader.php create mode 100644 server/vendor/composer/LICENSE create mode 100644 server/vendor/composer/autoload_classmap.php create mode 100644 server/vendor/composer/autoload_files.php create mode 100644 server/vendor/composer/autoload_namespaces.php create mode 100644 server/vendor/composer/autoload_psr4.php create mode 100644 server/vendor/composer/autoload_real.php create mode 100644 server/vendor/composer/installed.json create mode 100644 server/vendor/guzzlehttp/guzzle/.travis.yml create mode 100644 server/vendor/guzzlehttp/guzzle/CHANGELOG.md create mode 100644 server/vendor/guzzlehttp/guzzle/LICENSE create mode 100644 server/vendor/guzzlehttp/guzzle/README.md create mode 100644 server/vendor/guzzlehttp/guzzle/UPGRADING.md create mode 100644 server/vendor/guzzlehttp/guzzle/composer.json create mode 100644 server/vendor/guzzlehttp/guzzle/src/Client.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/ClientInterface.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Exception/SeekException.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/HandlerStack.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/MessageFormatter.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Middleware.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/Pool.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/RequestOptions.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/RetryMiddleware.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/TransferStats.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/UriTemplate.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/functions.php create mode 100644 server/vendor/guzzlehttp/guzzle/src/functions_include.php create mode 100644 server/vendor/guzzlehttp/promises/.gitignore create mode 100644 server/vendor/guzzlehttp/promises/.travis.yml create mode 100644 server/vendor/guzzlehttp/promises/CHANGELOG.md create mode 100644 server/vendor/guzzlehttp/promises/LICENSE create mode 100644 server/vendor/guzzlehttp/promises/Makefile create mode 100644 server/vendor/guzzlehttp/promises/README.md create mode 100644 server/vendor/guzzlehttp/promises/composer.json create mode 100644 server/vendor/guzzlehttp/promises/phpunit.xml.dist create mode 100644 server/vendor/guzzlehttp/promises/src/AggregateException.php create mode 100644 server/vendor/guzzlehttp/promises/src/CancellationException.php create mode 100644 server/vendor/guzzlehttp/promises/src/EachPromise.php create mode 100644 server/vendor/guzzlehttp/promises/src/FulfilledPromise.php create mode 100644 server/vendor/guzzlehttp/promises/src/Promise.php create mode 100644 server/vendor/guzzlehttp/promises/src/PromiseInterface.php create mode 100644 server/vendor/guzzlehttp/promises/src/PromisorInterface.php create mode 100644 server/vendor/guzzlehttp/promises/src/RejectedPromise.php create mode 100644 server/vendor/guzzlehttp/promises/src/RejectionException.php create mode 100644 server/vendor/guzzlehttp/promises/src/TaskQueue.php create mode 100644 server/vendor/guzzlehttp/promises/src/functions.php create mode 100644 server/vendor/guzzlehttp/promises/src/functions_include.php create mode 100644 server/vendor/guzzlehttp/promises/tests/AggregateExceptionTest.php create mode 100644 server/vendor/guzzlehttp/promises/tests/EachPromiseTest.php create mode 100644 server/vendor/guzzlehttp/promises/tests/FulfilledPromiseTest.php create mode 100644 server/vendor/guzzlehttp/promises/tests/NotPromiseInstance.php create mode 100644 server/vendor/guzzlehttp/promises/tests/PromiseTest.php create mode 100644 server/vendor/guzzlehttp/promises/tests/RejectedPromiseTest.php create mode 100644 server/vendor/guzzlehttp/promises/tests/RejectionExceptionTest.php create mode 100644 server/vendor/guzzlehttp/promises/tests/TaskQueueTest.php create mode 100644 server/vendor/guzzlehttp/promises/tests/Thennable.php create mode 100644 server/vendor/guzzlehttp/promises/tests/bootstrap.php create mode 100644 server/vendor/guzzlehttp/promises/tests/functionsTest.php create mode 100644 server/vendor/guzzlehttp/psr7/.gitignore create mode 100644 server/vendor/guzzlehttp/psr7/.travis.yml create mode 100644 server/vendor/guzzlehttp/psr7/CHANGELOG.md create mode 100644 server/vendor/guzzlehttp/psr7/LICENSE create mode 100644 server/vendor/guzzlehttp/psr7/Makefile create mode 100644 server/vendor/guzzlehttp/psr7/README.md create mode 100644 server/vendor/guzzlehttp/psr7/composer.json create mode 100644 server/vendor/guzzlehttp/psr7/phpunit.xml.dist create mode 100644 server/vendor/guzzlehttp/psr7/src/AppendStream.php create mode 100644 server/vendor/guzzlehttp/psr7/src/BufferStream.php create mode 100644 server/vendor/guzzlehttp/psr7/src/CachingStream.php create mode 100644 server/vendor/guzzlehttp/psr7/src/DroppingStream.php create mode 100644 server/vendor/guzzlehttp/psr7/src/FnStream.php create mode 100644 server/vendor/guzzlehttp/psr7/src/InflateStream.php create mode 100644 server/vendor/guzzlehttp/psr7/src/LazyOpenStream.php create mode 100644 server/vendor/guzzlehttp/psr7/src/LimitStream.php create mode 100644 server/vendor/guzzlehttp/psr7/src/MessageTrait.php create mode 100644 server/vendor/guzzlehttp/psr7/src/MultipartStream.php create mode 100644 server/vendor/guzzlehttp/psr7/src/NoSeekStream.php create mode 100644 server/vendor/guzzlehttp/psr7/src/PumpStream.php create mode 100644 server/vendor/guzzlehttp/psr7/src/Request.php create mode 100644 server/vendor/guzzlehttp/psr7/src/Response.php create mode 100644 server/vendor/guzzlehttp/psr7/src/Stream.php create mode 100644 server/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php create mode 100644 server/vendor/guzzlehttp/psr7/src/StreamWrapper.php create mode 100644 server/vendor/guzzlehttp/psr7/src/Uri.php create mode 100644 server/vendor/guzzlehttp/psr7/src/functions.php create mode 100644 server/vendor/guzzlehttp/psr7/src/functions_include.php create mode 100644 server/vendor/guzzlehttp/psr7/tests/AppendStreamTest.php create mode 100644 server/vendor/guzzlehttp/psr7/tests/BufferStreamTest.php create mode 100644 server/vendor/guzzlehttp/psr7/tests/CachingStreamTest.php create mode 100644 server/vendor/guzzlehttp/psr7/tests/DroppingStreamTest.php create mode 100644 server/vendor/guzzlehttp/psr7/tests/FnStreamTest.php create mode 100644 server/vendor/guzzlehttp/psr7/tests/FunctionsTest.php create mode 100644 server/vendor/guzzlehttp/psr7/tests/InflateStreamTest.php create mode 100644 server/vendor/guzzlehttp/psr7/tests/LazyOpenStreamTest.php create mode 100644 server/vendor/guzzlehttp/psr7/tests/LimitStreamTest.php create mode 100644 server/vendor/guzzlehttp/psr7/tests/MultipartStreamTest.php create mode 100644 server/vendor/guzzlehttp/psr7/tests/NoSeekStreamTest.php create mode 100644 server/vendor/guzzlehttp/psr7/tests/PumpStreamTest.php create mode 100644 server/vendor/guzzlehttp/psr7/tests/RequestTest.php create mode 100644 server/vendor/guzzlehttp/psr7/tests/ResponseTest.php create mode 100644 server/vendor/guzzlehttp/psr7/tests/StreamDecoratorTraitTest.php create mode 100644 server/vendor/guzzlehttp/psr7/tests/StreamTest.php create mode 100644 server/vendor/guzzlehttp/psr7/tests/StreamWrapperTest.php create mode 100644 server/vendor/guzzlehttp/psr7/tests/UriTest.php create mode 100644 server/vendor/guzzlehttp/psr7/tests/bootstrap.php create mode 100644 server/vendor/justinrainbow/json-schema/.gitattributes create mode 100644 server/vendor/justinrainbow/json-schema/LICENSE create mode 100644 server/vendor/justinrainbow/json-schema/README.md create mode 100755 server/vendor/justinrainbow/json-schema/bin/validate-json create mode 100644 server/vendor/justinrainbow/json-schema/composer.json create mode 100644 server/vendor/justinrainbow/json-schema/phpunit.xml.dist create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSourceUriException.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/RefResolver.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/AbstractRetriever.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/Curl.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/PredefinedArray.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/UriRetrieverInterface.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php create mode 100644 server/vendor/justinrainbow/json-schema/src/JsonSchema/Validator.php create mode 160000 server/vendor/php-opencloud/openstack create mode 100644 server/vendor/psr/http-message/LICENSE create mode 100644 server/vendor/psr/http-message/README.md create mode 100644 server/vendor/psr/http-message/composer.json create mode 100644 server/vendor/psr/http-message/src/MessageInterface.php create mode 100644 server/vendor/psr/http-message/src/RequestInterface.php create mode 100644 server/vendor/psr/http-message/src/ResponseInterface.php create mode 100644 server/vendor/psr/http-message/src/ServerRequestInterface.php create mode 100644 server/vendor/psr/http-message/src/StreamInterface.php create mode 100644 server/vendor/psr/http-message/src/UploadedFileInterface.php create mode 100644 server/vendor/psr/http-message/src/UriInterface.php 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 0000000000000000000000000000000000000000..02812376d6f60c80ddbf702c112b29475d20a479 GIT binary patch literal 1514291 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%0A}Fp%*BiJr(|{3}OoLJCz6;V?^Ol?iKQa`rm) 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�D;H-LwOzg^(Z0&(idR< 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%0DIuggJtTjB9IURz-`;y;J3Tdh`Q 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

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

MB0m9<=mcHHp@x+9Oj-#d;2RT_PwE_$JkN|V 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 q+qR27y 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 literal 0 HcmV?d00001 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 @@ + + * Jordi Boggiano + * + * 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 + * @author Jordi Boggiano + * @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 @@ + $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 @@ + 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 @@ + $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 + +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 + + + + + + Get a list of groups + + + Uses a search query to get a list of groups + + + + Create a group + + + + + Delete a group by ID + + + + + + + Update a group + + + + + + +``` + +**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 @@ + '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 @@ +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 @@ +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 @@ +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 @@ + 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 @@ +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: + // ... (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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +>>>>>>>\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 @@ +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 @@ + $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 @@ + 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 @@ + 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 @@ +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 @@ +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 @@ + 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 @@ +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 @@ + + +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 +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 @@ + + + + + tests + + + + + src + + src/ + + + + 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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ + + * while ($eventLoop->isRunning()) { + * GuzzleHttp\Promise\queue()->run(); + * } + * + * + * @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 @@ +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 @@ + 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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 + +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 @@ + + + + + tests + + + + + src + + src/ + + + + 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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ + '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 @@ + [ + '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 @@ +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 @@ +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 @@ + 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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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( + '', + 'rel' => 'front', + 'type' => 'image/jpeg', + ), + array( + '', + 'rel' => 'back', + 'type' => 'image/jpeg', + ), + ); + return array( + array( + '; rel="front"; type="image/jpeg", ; rel=back; type="image/jpeg"', + $res1 + ), + array( + '; rel="front"; type="image/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( + '; rel="side"; type="image/jpeg",; rel=side; type="image/jpeg"', + array( + array('', 'rel' => 'side', 'type' => 'image/jpeg'), + array('', '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 @@ +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 @@ +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 @@ +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 @@ +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 = <<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 = <<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 = <<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 @@ +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 @@ + ['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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 @@ +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 + + */ + +/** + * 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 << 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: ; 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 @@ + + + + + + tests + + + + + + ./src/JsonSchema/ + + + 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 @@ + + * @author Bruno Prieto Reis + */ +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 @@ + + * @author Bruno Prieto Reis + */ +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 @@ + + */ +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 @@ + + * @author Bruno Prieto Reis + */ +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 @@ +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 @@ + + * @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 @@ + + * @author Bruno Prieto Reis + */ +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 @@ + + * @author Bruno Prieto Reis + */ +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 @@ + + * @author Bruno Prieto Reis + */ +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 @@ + + * @author Bruno Prieto Reis + */ +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 @@ + + * @author Bruno Prieto Reis + */ +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 @@ + + * @author Bruno Prieto Reis + */ +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 @@ + + * @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 @@ + + */ +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 @@ + + */ +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 @@ + + */ +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 @@ + '{ ... }', + * '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 @@ + + */ +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 @@ + + */ +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('|((?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 @@ + + */ +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 @@ + + * @author Bruno Prieto Reis + * @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 index 0000000..8a6ec70 --- /dev/null +++ b/server/vendor/php-opencloud/openstack @@ -0,0 +1 @@ +Subproject commit 8a6ec703597f0440e558d8f1f21b2ff303117dbd 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 @@ +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 @@ +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 @@ + + * [user-info@]host[:port] + * + * + * 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(); +}