summaryrefslogtreecommitdiff
path: root/www/wiki/vendor/guzzlehttp
diff options
context:
space:
mode:
authorYaco <franco@reevo.org>2020-06-04 11:01:00 -0300
committerYaco <franco@reevo.org>2020-06-04 11:01:00 -0300
commitfc7369835258467bf97eb64f184b93691f9a9fd5 (patch)
treedaabd60089d2dd76d9f5fb416b005fbe159c799d /www/wiki/vendor/guzzlehttp
first commit
Diffstat (limited to 'www/wiki/vendor/guzzlehttp')
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/.editorconfig12
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/.gitignore4
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/.travis.yml43
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/CHANGELOG.md118
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/LICENSE19
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/Makefile46
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/README.rst46
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/composer.json43
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/docs/Makefile153
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/docs/client_handlers.rst173
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/docs/client_middleware.rst165
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/docs/conf.py23
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/docs/futures.rst164
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/docs/index.rst50
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/docs/requirements.txt1
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/docs/spec.rst311
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/docs/testing.rst74
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/phpunit.xml.dist14
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Client/ClientUtils.php74
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Client/CurlFactory.php560
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Client/CurlHandler.php135
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Client/CurlMultiHandler.php248
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Client/Middleware.php58
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Client/MockHandler.php52
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Client/StreamHandler.php414
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Core.php364
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Exception/CancelledException.php7
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Exception/CancelledFutureAccessException.php4
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Exception/ConnectException.php7
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Exception/RingException.php4
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Future/BaseFutureTrait.php125
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureArray.php43
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureValue.php57
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Future/FutureArray.php40
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Future/FutureArrayInterface.php11
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Future/FutureInterface.php40
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Future/FutureValue.php12
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/src/Future/MagicFutureTrait.php32
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/tests/Client/CurlFactoryTest.php821
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/tests/Client/CurlHandlerTest.php96
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/tests/Client/CurlMultiHandlerTest.php181
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/tests/Client/MiddlewareTest.php65
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/tests/Client/MockHandlerTest.php86
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/tests/Client/Server.php183
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/tests/Client/StreamHandlerTest.php480
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/tests/Client/server.js241
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/tests/CoreTest.php336
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureArrayTest.php21
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureValueTest.php46
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/tests/Future/FutureArrayTest.php56
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/tests/Future/FutureValueTest.php109
-rw-r--r--www/wiki/vendor/guzzlehttp/ringphp/tests/bootstrap.php11
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/.gitignore6
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/.travis.yml17
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/CHANGELOG.rst94
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/LICENSE19
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/Makefile19
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/README.rst36
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/composer.json28
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/phpunit.xml.dist17
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/AppendStream.php220
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/AsyncReadStream.php207
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/BufferStream.php138
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/CachingStream.php122
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/DroppingStream.php42
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/Exception/CannotAttachException.php4
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/Exception/SeekException.php27
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/FnStream.php147
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/GuzzleStreamWrapper.php117
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/InflateStream.php27
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/LazyOpenStream.php37
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/LimitStream.php161
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/MetadataStreamInterface.php11
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/NoSeekStream.php25
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/NullStream.php78
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/PumpStream.php161
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/Stream.php261
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/StreamDecoratorTrait.php143
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/StreamInterface.php159
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/src/Utils.php196
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/tests/AppendStreamTest.php178
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/tests/AsyncReadStreamTest.php186
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/tests/BufferStreamTest.php69
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/tests/CachingStreamTest.php136
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/tests/DroppingStreamTest.php26
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/tests/Exception/SeekExceptionTest.php16
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/tests/FnStreamTest.php89
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/tests/GuzzleStreamWrapperTest.php99
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/tests/InflateStreamTest.php16
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/tests/LazyOpenStreamTest.php64
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/tests/LimitStreamTest.php133
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/tests/NoSeekStreamTest.php41
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/tests/NullStreamTest.php39
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/tests/PumpStreamTest.php77
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/tests/StreamDecoratorTraitTest.php147
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/tests/StreamTest.php252
-rw-r--r--www/wiki/vendor/guzzlehttp/streams/tests/UtilsTest.php155
97 files changed, 10720 insertions, 0 deletions
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/.editorconfig b/www/wiki/vendor/guzzlehttp/ringphp/.editorconfig
new file mode 100644
index 00000000..70dabca1
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/.editorconfig
@@ -0,0 +1,12 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = space
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[{Makefile,*.mk}]
+indent_style = tab
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/.gitignore b/www/wiki/vendor/guzzlehttp/ringphp/.gitignore
new file mode 100644
index 00000000..290a9452
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/.gitignore
@@ -0,0 +1,4 @@
+vendor
+build/artifacts/
+composer.lock
+docs/_build/
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/.travis.yml b/www/wiki/vendor/guzzlehttp/ringphp/.travis.yml
new file mode 100644
index 00000000..18562e42
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/.travis.yml
@@ -0,0 +1,43 @@
+language: php
+
+cache:
+ directories:
+ - $HOME/.composer/cache/files
+
+php:
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+ - 7.1
+ - 7.2
+ - hhvm
+ - nightly
+
+env:
+ global:
+ - TEST_COMMAND="composer test"
+
+matrix:
+ allow_failures:
+ - php: hhvm
+ - php: nightly
+ fast_finish: true
+ include:
+ - php: 5.4
+ env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest"
+
+before_install:
+ - if [[ $COVERAGE != true ]]; then phpenv config-rm xdebug.ini || true; fi
+
+install:
+ # To be removed when this issue will be resolved: https://github.com/composer/composer/issues/5355
+ - if [[ "$COMPOSER_FLAGS" == *"--prefer-lowest"* ]]; then travis_retry composer update --prefer-dist --no-interaction --prefer-stable --quiet; fi
+ - travis_retry composer update ${COMPOSER_FLAGS} --prefer-dist --no-interaction
+
+before_script:
+ - ~/.nvm/nvm.sh install v0.6.14
+ - ~/.nvm/nvm.sh run v0.6.14
+
+script:
+ - $TEST_COMMAND
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/CHANGELOG.md b/www/wiki/vendor/guzzlehttp/ringphp/CHANGELOG.md
new file mode 100644
index 00000000..8e12bf3c
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/CHANGELOG.md
@@ -0,0 +1,118 @@
+# Changelog
+
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
+
+
+## [Unreleased]
+
+
+## [1.1.1] - 2018-07-31
+
+### Fixed
+
+- `continue` keyword usage on PHP 7.3
+
+
+## [1.1.0] - 2015-05-19
+
+### Added
+
+- Added `CURL_HTTP_VERSION_2_0`
+
+### Changed
+
+- The PHP stream wrapper handler now sets `allow_self_signed` to `false` to
+ match the cURL handler when `verify` is set to `true` or a certificate file.
+- Ensuring that a directory exists before using the `save_to` option.
+- Response protocol version is now correctly extracted from a response.
+
+### Fixed
+
+- Fixed a bug in which the result of `CurlFactory::retryFailedRewind` did not
+ return an array.
+
+
+## [1.0.7] - 2015-03-29
+
+### Fixed
+
+- PHP 7 fixes.
+
+
+## [1.0.6] - 2015-02-26
+
+### Changed
+
+- The multi handle of the CurlMultiHandler is now created lazily.
+
+### Fixed
+
+- Bug fix: futures now extend from React's PromiseInterface to ensure that they
+ are properly forwarded down the promise chain.
+
+
+## [1.0.5] - 2014-12-10
+
+### Added
+
+- Adding more error information to PHP stream wrapper exceptions.
+- Added digest auth integration test support to test server.
+
+
+## [1.0.4] - 2014-12-01
+
+### Added
+
+- Added support for older versions of cURL that do not have CURLOPT_TIMEOUT_MS.
+- Added a fix to the StreamHandler to return a `FutureArrayInterface` when an
+
+### Changed
+
+- Setting debug to `false` does not enable debug output. error occurs.
+
+
+## [1.0.3] - 2014-11-03
+
+### Fixed
+
+- Setting the `header` stream option as a string to be compatible with GAE.
+- Header parsing now ensures that header order is maintained in the parsed
+ message.
+
+
+## [1.0.2] - 2014-10-28
+
+### Fixed
+
+- Now correctly honoring a `version` option is supplied in a request.
+ See https://github.com/guzzle/RingPHP/pull/8
+
+
+## [1.0.1] - 2014-10-26
+
+### Fixed
+
+- Fixed a header parsing issue with the `CurlHandler` and `CurlMultiHandler`
+ that caused cURL requests with multiple responses to merge repsonses together
+ (e.g., requests with digest authentication).
+
+
+## 1.0.0 - 2014-10-12
+
+- Initial release
+
+
+[Unreleased]: https://github.com/guzzle/RingPHP/compare/1.1.1...HEAD
+[1.1.1]: https://github.com/guzzle/RingPHP/compare/1.1.0...1.1.1
+[1.1.0]: https://github.com/guzzle/RingPHP/compare/1.0.7...1.1.0
+[1.0.7]: https://github.com/guzzle/RingPHP/compare/1.0.6...1.0.7
+[1.0.6]: https://github.com/guzzle/RingPHP/compare/1.0.5...1.0.6
+[1.0.5]: https://github.com/guzzle/RingPHP/compare/1.0.4...1.0.5
+[1.0.4]: https://github.com/guzzle/RingPHP/compare/1.0.3...1.0.4
+[1.0.3]: https://github.com/guzzle/RingPHP/compare/1.0.2...1.0.3
+[1.0.2]: https://github.com/guzzle/RingPHP/compare/1.0.1...1.0.2
+[1.0.1]: https://github.com/guzzle/RingPHP/compare/1.0.0...1.0.1
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/LICENSE b/www/wiki/vendor/guzzlehttp/ringphp/LICENSE
new file mode 100644
index 00000000..71d3b783
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2014 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/Makefile b/www/wiki/vendor/guzzlehttp/ringphp/Makefile
new file mode 100644
index 00000000..21c812e3
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/Makefile
@@ -0,0 +1,46 @@
+all: clean coverage docs
+
+docs:
+ cd docs && make html
+
+view-docs:
+ open docs/_build/html/index.html
+
+start-server: stop-server
+ node tests/Client/server.js &> /dev/null &
+
+stop-server:
+ @PID=$(shell ps axo pid,command \
+ | grep 'tests/Client/server.js' \
+ | grep -v grep \
+ | cut -f 1 -d " "\
+ ) && [ -n "$$PID" ] && kill $$PID || true
+
+test: start-server
+ vendor/bin/phpunit $(TEST)
+ $(MAKE) stop-server
+
+coverage: start-server
+ vendor/bin/phpunit --coverage-html=build/artifacts/coverage $(TEST)
+ $(MAKE) stop-server
+
+view-coverage:
+ open build/artifacts/coverage/index.html
+
+clean:
+ rm -rf build/artifacts/*
+ cd docs && make clean
+
+tag:
+ $(if $(TAG),,$(error TAG is not defined. Pass via "make tag TAG=4.2.1"))
+ @echo Tagging $(TAG)
+ chag update -m '$(TAG) ()'
+ git add -A
+ git commit -m '$(TAG) release'
+ chag tag
+
+perf: start-server
+ php tests/perf.php
+ $(MAKE) stop-server
+
+.PHONY: docs
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/README.rst b/www/wiki/vendor/guzzlehttp/ringphp/README.rst
new file mode 100644
index 00000000..10374e81
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/README.rst
@@ -0,0 +1,46 @@
+=======
+RingPHP
+=======
+
+Provides a simple API and specification that abstracts away the details of HTTP
+into a single PHP function. RingPHP be used to power HTTP clients and servers
+through a PHP function that accepts a request hash and returns a response hash
+that is fulfilled using a `promise <https://github.com/reactphp/promise>`_,
+allowing RingPHP to support both synchronous and asynchronous workflows.
+
+By abstracting the implementation details of different HTTP clients and
+servers, RingPHP allows you to utilize pluggable HTTP clients and servers
+without tying your application to a specific implementation.
+
+.. code-block:: php
+
+ <?php
+ require 'vendor/autoload.php';
+
+ use GuzzleHttp\Ring\Client\CurlHandler;
+
+ $handler = new CurlHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => [
+ 'host' => ['www.google.com'],
+ 'x-foo' => ['baz']
+ ]
+ ]);
+
+ $response->then(function (array $response) {
+ echo $response['status'];
+ });
+
+ $response->wait();
+
+RingPHP is inspired by Clojure's `Ring <https://github.com/ring-clojure/ring>`_,
+which, in turn, was inspired by Python's WSGI and Ruby's Rack. RingPHP is
+utilized as the handler layer in `Guzzle <http://guzzlephp.org>`_ 5.0+ to send
+HTTP requests.
+
+Documentation
+-------------
+
+See http://ringphp.readthedocs.org/ for the full online documentation.
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/composer.json b/www/wiki/vendor/guzzlehttp/ringphp/composer.json
new file mode 100644
index 00000000..8df60ecc
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/composer.json
@@ -0,0 +1,43 @@
+{
+ "name": "guzzlehttp/ringphp",
+ "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "require": {
+ "php": ">=5.4.0",
+ "guzzlehttp/streams": "~3.0",
+ "react/promise": "~2.0"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "phpunit/phpunit": "~4.0"
+ },
+ "suggest": {
+ "ext-curl": "Guzzle will use specific adapters if cURL is present"
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Ring\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "GuzzleHttp\\Tests\\Ring\\": "tests/"
+ }
+ },
+ "scripts": {
+ "test": "make test",
+ "test-ci": "make coverage"
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1-dev"
+ }
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/docs/Makefile b/www/wiki/vendor/guzzlehttp/ringphp/docs/Makefile
new file mode 100644
index 00000000..51270aa5
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/docs/Makefile
@@ -0,0 +1,153 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " texinfo to make Texinfo files"
+ @echo " info to make Texinfo files and run them through makeinfo"
+ @echo " gettext to make PO message catalogs"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ -rm -rf $(BUILDDIR)/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/GuzzleRing.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/GuzzleRing.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/GuzzleRing"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/GuzzleRing"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+info:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+ @echo
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/docs/client_handlers.rst b/www/wiki/vendor/guzzlehttp/ringphp/docs/client_handlers.rst
new file mode 100644
index 00000000..3151f002
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/docs/client_handlers.rst
@@ -0,0 +1,173 @@
+===============
+Client Handlers
+===============
+
+Client handlers accept a request array and return a future response array that
+can be used synchronously as an array or asynchronously using a promise.
+
+Built-In Handlers
+-----------------
+
+RingPHP comes with three built-in client handlers.
+
+Stream Handler
+~~~~~~~~~~~~~~
+
+The ``GuzzleHttp\Ring\Client\StreamHandler`` uses PHP's
+`http stream wrapper <http://php.net/manual/en/wrappers.http.php>`_ to send
+requests.
+
+.. note::
+
+ This handler cannot send requests concurrently.
+
+You can provide an associative array of custom stream context options to the
+StreamHandler using the ``stream_context`` key of the ``client`` request
+option.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\StreamHandler;
+
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['host' => ['httpbin.org']],
+ 'client' => [
+ 'stream_context' => [
+ 'http' => [
+ 'request_fulluri' => true,
+ 'method' => 'HEAD'
+ ],
+ 'socket' => [
+ 'bindto' => '127.0.0.1:0'
+ ],
+ 'ssl' => [
+ 'verify_peer' => false
+ ]
+ ]
+ ]
+ ]);
+
+ // Even though it's already completed, you can still use a promise
+ $response->then(function ($response) {
+ echo $response['status']; // 200
+ });
+
+ // Or access the response using the future interface
+ echo $response['status']; // 200
+
+cURL Handler
+~~~~~~~~~~~~
+
+The ``GuzzleHttp\Ring\Client\CurlHandler`` can be used with PHP 5.5+ to send
+requests using cURL easy handles. This handler is great for sending requests
+one at a time because the execute and select loop is implemented in C code
+which executes faster and consumes less memory than using PHP's
+``curl_multi_*`` interface.
+
+.. note::
+
+ This handler cannot send requests concurrently.
+
+When using the CurlHandler, custom curl options can be specified as an
+associative array of `cURL option constants <http://php.net/manual/en/curl.constants.php>`_
+mapping to values in the ``client`` option of a requst using the **curl** key.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\CurlHandler;
+
+ $handler = new CurlHandler();
+
+ $request = [
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['curl' => [CURLOPT_LOW_SPEED_LIMIT => 10]]
+ ];
+
+ $response = $handler($request);
+
+ // The response can be used directly as an array.
+ echo $response['status']; // 200
+
+ // Or, it can be used as a promise (that has already fulfilled).
+ $response->then(function ($response) {
+ echo $response['status']; // 200
+ });
+
+cURL Multi Handler
+~~~~~~~~~~~~~~~~~~
+
+The ``GuzzleHttp\Ring\Client\CurlMultiHandler`` transfers requests using
+cURL's `multi API <http://curl.haxx.se/libcurl/c/libcurl-multi.html>`_. The
+``CurlMultiHandler`` is great for sending requests concurrently.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\CurlMultiHandler;
+
+ $handler = new CurlMultiHandler();
+
+ $request = [
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]]
+ ];
+
+ // this call returns a future array immediately.
+ $response = $handler($request);
+
+ // Ideally, you should use the promise API to not block.
+ $response
+ ->then(function ($response) {
+ // Got the response at some point in the future
+ echo $response['status']; // 200
+ // Don't break the chain
+ return $response;
+ })->then(function ($response) {
+ // ...
+ });
+
+ // If you really need to block, then you can use the response as an
+ // associative array. This will block until it has completed.
+ echo $response['status']; // 200
+
+Just like the ``CurlHandler``, the ``CurlMultiHandler`` accepts custom curl
+option in the ``curl`` key of the ``client`` request option.
+
+Mock Handler
+~~~~~~~~~~~~
+
+The ``GuzzleHttp\Ring\Client\MockHandler`` is used to return mock responses.
+When constructed, the handler can be configured to return the same response
+array over and over, a future response, or a the evaluation of a callback
+function.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\MockHandler;
+
+ // Return a canned response.
+ $mock = new MockHandler(['status' => 200]);
+ $response = $mock([]);
+ assert(200 == $response['status']);
+ assert([] == $response['headers']);
+
+Implementing Handlers
+---------------------
+
+Client handlers are just PHP callables (functions or classes that have the
+``__invoke`` magic method). The callable accepts a request array and MUST
+return an instance of ``GuzzleHttp\Ring\Future\FutureArrayInterface`` so that
+the response can be used by both blocking and non-blocking consumers.
+
+Handlers need to follow a few simple rules:
+
+1. Do not throw exceptions. If an error is encountered, return an array that
+ contains the ``error`` key that maps to an ``\Exception`` value.
+2. If the request has a ``delay`` client option, then the handler should only
+ send the request after the specified delay time in seconds. Blocking
+ handlers may find it convenient to just let the
+ ``GuzzleHttp\Ring\Core::doSleep($request)`` function handle this for them.
+3. Always return an instance of ``GuzzleHttp\Ring\Future\FutureArrayInterface``.
+4. Complete any outstanding requests when the handler is destructed.
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/docs/client_middleware.rst b/www/wiki/vendor/guzzlehttp/ringphp/docs/client_middleware.rst
new file mode 100644
index 00000000..5a2c1a8a
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/docs/client_middleware.rst
@@ -0,0 +1,165 @@
+=================
+Client Middleware
+=================
+
+Middleware intercepts requests before they are sent over the wire and can be
+used to add functionality to handlers.
+
+Modifying Requests
+------------------
+
+Let's say you wanted to modify requests before they are sent over the wire
+so that they always add specific headers. This can be accomplished by creating
+a function that accepts a handler and returns a new function that adds the
+composed behavior.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\CurlHandler;
+
+ $handler = new CurlHandler();
+
+ $addHeaderHandler = function (callable $handler, array $headers = []) {
+ return function (array $request) use ($handler, $headers) {
+ // Add our custom headers
+ foreach ($headers as $key => $value) {
+ $request['headers'][$key] = $value;
+ }
+
+ // Send the request using the handler and return the response.
+ return $handler($request);
+ }
+ };
+
+ // Create a new handler that adds headers to each request.
+ $handler = $addHeaderHandler($handler, [
+ 'X-AddMe' => 'hello',
+ 'Authorization' => 'Basic xyz'
+ ]);
+
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['Host' => ['httpbin.org']]
+ ]);
+
+Modifying Responses
+-------------------
+
+You can change a response as it's returned from a middleware. Remember that
+responses returned from an handler (including middleware) must implement
+``GuzzleHttp\Ring\Future\FutureArrayInterface``. In order to be a good citizen,
+you should not expect that the responses returned through your middleware will
+be completed synchronously. Instead, you should use the
+``GuzzleHttp\Ring\Core::proxy()`` function to modify the response when the
+underlying promise is resolved. This function is a helper function that makes it
+easy to create a new instance of ``FutureArrayInterface`` that wraps an existing
+``FutureArrayInterface`` object.
+
+Let's say you wanted to add headers to a response as they are returned from
+your middleware, but you want to make sure you aren't causing future
+responses to be dereferenced right away. You can achieve this by modifying the
+incoming request and using the ``Core::proxy`` function.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Core;
+ use GuzzleHttp\Ring\Client\CurlHandler;
+
+ $handler = new CurlHandler();
+
+ $responseHeaderHandler = function (callable $handler, array $headers) {
+ return function (array $request) use ($handler, $headers) {
+ // Send the request using the wrapped handler.
+ return Core::proxy($handler($request), function ($response) use ($headers) {
+ // Add the headers to the response when it is available.
+ foreach ($headers as $key => $value) {
+ $response['headers'][$key] = (array) $value;
+ }
+ // Note that you can return a regular response array when using
+ // the proxy method.
+ return $response;
+ });
+ }
+ };
+
+ // Create a new handler that adds headers to each response.
+ $handler = $responseHeaderHandler($handler, ['X-Header' => 'hello!']);
+
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['Host' => ['httpbin.org']]
+ ]);
+
+ assert($response['headers']['X-Header'] == 'hello!');
+
+Built-In Middleware
+-------------------
+
+RingPHP comes with a few basic client middlewares that modify requests
+and responses.
+
+Streaming Middleware
+~~~~~~~~~~~~~~~~~~~~
+
+If you want to send all requests with the ``streaming`` option to a specific
+handler but other requests to a different handler, then use the streaming
+middleware.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\CurlHandler;
+ use GuzzleHttp\Ring\Client\StreamHandler;
+ use GuzzleHttp\Ring\Client\Middleware;
+
+ $defaultHandler = new CurlHandler();
+ $streamingHandler = new StreamHandler();
+ $streamingHandler = Middleware::wrapStreaming(
+ $defaultHandler,
+ $streamingHandler
+ );
+
+ // Send the request using the streaming handler.
+ $response = $streamingHandler([
+ 'http_method' => 'GET',
+ 'headers' => ['Host' => ['www.google.com']],
+ 'stream' => true
+ ]);
+
+ // Send the request using the default handler.
+ $response = $streamingHandler([
+ 'http_method' => 'GET',
+ 'headers' => ['Host' => ['www.google.com']]
+ ]);
+
+Future Middleware
+~~~~~~~~~~~~~~~~~
+
+If you want to send all requests with the ``future`` option to a specific
+handler but other requests to a different handler, then use the future
+middleware.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\CurlHandler;
+ use GuzzleHttp\Ring\Client\CurlMultiHandler;
+ use GuzzleHttp\Ring\Client\Middleware;
+
+ $defaultHandler = new CurlHandler();
+ $futureHandler = new CurlMultiHandler();
+ $futureHandler = Middleware::wrapFuture(
+ $defaultHandler,
+ $futureHandler
+ );
+
+ // Send the request using the blocking CurlHandler.
+ $response = $futureHandler([
+ 'http_method' => 'GET',
+ 'headers' => ['Host' => ['www.google.com']]
+ ]);
+
+ // Send the request using the non-blocking CurlMultiHandler.
+ $response = $futureHandler([
+ 'http_method' => 'GET',
+ 'headers' => ['Host' => ['www.google.com']],
+ 'future' => true
+ ]);
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/docs/conf.py b/www/wiki/vendor/guzzlehttp/ringphp/docs/conf.py
new file mode 100644
index 00000000..c6404aa1
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/docs/conf.py
@@ -0,0 +1,23 @@
+import sys, os
+import sphinx_rtd_theme
+from sphinx.highlighting import lexers
+from pygments.lexers.web import PhpLexer
+
+
+lexers['php'] = PhpLexer(startinline=True, linenos=1)
+lexers['php-annotations'] = PhpLexer(startinline=True, linenos=1)
+primary_domain = 'php'
+
+extensions = []
+templates_path = ['_templates']
+source_suffix = '.rst'
+master_doc = 'index'
+project = u'RingPHP'
+copyright = u'2014, Michael Dowling'
+version = '1.0.0-alpha'
+exclude_patterns = ['_build']
+
+html_title = "RingPHP"
+html_short_title = "RingPHP"
+html_theme = "sphinx_rtd_theme"
+html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/docs/futures.rst b/www/wiki/vendor/guzzlehttp/ringphp/docs/futures.rst
new file mode 100644
index 00000000..af29cb37
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/docs/futures.rst
@@ -0,0 +1,164 @@
+=======
+Futures
+=======
+
+Futures represent a computation that may have not yet completed. RingPHP
+uses hybrid of futures and promises to provide a consistent API that can be
+used for both blocking and non-blocking consumers.
+
+Promises
+--------
+
+You can get the result of a future when it is ready using the promise interface
+of a future. Futures expose a promise API via a ``then()`` method that utilizes
+`React's promise library <https://github.com/reactphp/promise>`_. You should
+use this API when you do not wish to block.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\CurlMultiHandler;
+
+ $request = [
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['host' => ['httpbin.org']]
+ ];
+
+ $response = $handler($request);
+
+ // Use the then() method to use the promise API of the future.
+ $response->then(function ($response) {
+ echo $response['status'];
+ });
+
+You can get the promise used by a future, an instance of
+``React\Promise\PromiseInterface``, by calling the ``promise()`` method.
+
+.. code-block:: php
+
+ $response = $handler($request);
+ $promise = $response->promise();
+ $promise->then(function ($response) {
+ echo $response['status'];
+ });
+
+This promise value can be used with React's
+`aggregate promise functions <https://github.com/reactphp/promise#functions>`_.
+
+Waiting
+-------
+
+You can wait on a future to complete and retrieve the value, or *dereference*
+the future, using the ``wait()`` method. Calling the ``wait()`` method of a
+future will block until the result is available. The result is then returned or
+an exception is thrown if and exception was encountered while waiting on the
+the result. Subsequent calls to dereference a future will return the previously
+completed result or throw the previously encountered exception. Futures can be
+cancelled, which stops the computation if possible.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\CurlMultiHandler;
+
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['host' => ['httpbin.org']]
+ ]);
+
+ // You can explicitly call block to wait on a result.
+ $realizedResponse = $response->wait();
+
+ // Future responses can be used like a regular PHP array.
+ echo $response['status'];
+
+In addition to explicitly calling the ``wait()`` function, using a future like
+a normal value will implicitly trigger the ``wait()`` function.
+
+Future Responses
+----------------
+
+RingPHP uses futures to return asynchronous responses immediately. Client
+handlers always return future responses that implement
+``GuzzleHttp\Ring\Future\ArrayFutureInterface``. These future responses act
+just like normal PHP associative arrays for blocking access and provide a
+promise interface for non-blocking access.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\CurlMultiHandler;
+
+ $handler = new CurlMultiHandler();
+
+ $request = [
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['Host' => ['www.google.com']]
+ ];
+
+ $response = $handler($request);
+
+ // Use the promise API for non-blocking access to the response. The actual
+ // response value will be delivered to the promise.
+ $response->then(function ($response) {
+ echo $response['status'];
+ });
+
+ // You can wait (block) until the future is completed.
+ $response->wait();
+
+ // This will implicitly call wait(), and will block too!
+ $response['status'];
+
+.. important::
+
+ Futures that are not completed by the time the underlying handler is
+ destructed will be completed when the handler is shutting down.
+
+Cancelling
+----------
+
+Futures can be cancelled if they have not already been dereferenced.
+
+RingPHP futures are typically implemented with the
+``GuzzleHttp\Ring\Future\BaseFutureTrait``. This trait provides the cancellation
+functionality that should be common to most implementations. Cancelling a
+future response will try to prevent the request from sending over the wire.
+
+When a future is cancelled, the cancellation function is invoked and performs
+the actual work needed to cancel the request from sending if possible
+(e.g., telling an event loop to stop sending a request or to close a socket).
+If no cancellation function is provided, then a request cannot be cancelled. If
+a cancel function is provided, then it should accept the future as an argument
+and return true if the future was successfully cancelled or false if it could
+not be cancelled.
+
+Wrapping an existing Promise
+----------------------------
+
+You can easily create a future from any existing promise using the
+``GuzzleHttp\Ring\Future\FutureValue`` class. This class's constructor
+accepts a promise as the first argument, a wait function as the second
+argument, and a cancellation function as the third argument. The dereference
+function is used to force the promise to resolve (for example, manually ticking
+an event loop). The cancel function is optional and is used to tell the thing
+that created the promise that it can stop computing the result (for example,
+telling an event loop to stop transferring a request).
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Future\FutureValue;
+ use React\Promise\Deferred;
+
+ $deferred = new Deferred();
+ $promise = $deferred->promise();
+
+ $f = new FutureValue(
+ $promise,
+ function () use ($deferred) {
+ // This function is responsible for blocking and resolving the
+ // promise. Here we pass in a reference to the deferred so that
+ // it can be resolved or rejected.
+ $deferred->resolve('foo');
+ }
+ );
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/docs/index.rst b/www/wiki/vendor/guzzlehttp/ringphp/docs/index.rst
new file mode 100644
index 00000000..4bbce631
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/docs/index.rst
@@ -0,0 +1,50 @@
+=======
+RingPHP
+=======
+
+Provides a simple API and specification that abstracts away the details of HTTP
+into a single PHP function. RingPHP be used to power HTTP clients and servers
+through a PHP function that accepts a request hash and returns a response hash
+that is fulfilled using a `promise <https://github.com/reactphp/promise>`_,
+allowing RingPHP to support both synchronous and asynchronous workflows.
+
+By abstracting the implementation details of different HTTP clients and
+servers, RingPHP allows you to utilize pluggable HTTP clients and servers
+without tying your application to a specific implementation.
+
+.. toctree::
+ :maxdepth: 2
+
+ spec
+ futures
+ client_middleware
+ client_handlers
+ testing
+
+.. code-block:: php
+
+ <?php
+ require 'vendor/autoload.php';
+
+ use GuzzleHttp\Ring\Client\CurlHandler;
+
+ $handler = new CurlHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => [
+ 'host' => ['www.google.com'],
+ 'x-foo' => ['baz']
+ ]
+ ]);
+
+ $response->then(function (array $response) {
+ echo $response['status'];
+ });
+
+ $response->wait();
+
+RingPHP is inspired by Clojure's `Ring <https://github.com/ring-clojure/ring>`_,
+which, in turn, was inspired by Python's WSGI and Ruby's Rack. RingPHP is
+utilized as the handler layer in `Guzzle <http://guzzlephp.org>`_ 5.0+ to send
+HTTP requests.
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/docs/requirements.txt b/www/wiki/vendor/guzzlehttp/ringphp/docs/requirements.txt
new file mode 100644
index 00000000..483a4e96
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/docs/requirements.txt
@@ -0,0 +1 @@
+sphinx_rtd_theme
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/docs/spec.rst b/www/wiki/vendor/guzzlehttp/ringphp/docs/spec.rst
new file mode 100644
index 00000000..bc910789
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/docs/spec.rst
@@ -0,0 +1,311 @@
+=============
+Specification
+=============
+
+RingPHP applications consist of handlers, requests, responses, and
+middleware.
+
+Handlers
+--------
+
+Handlers are implemented as a PHP ``callable`` that accept a request array
+and return a response array (``GuzzleHttp\Ring\Future\FutureArrayInterface``).
+
+For example:
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Future\CompletedFutureArray;
+
+ $mockHandler = function (array $request) {
+ return new CompletedFutureArray([
+ 'status' => 200,
+ 'headers' => ['X-Foo' => ['Bar']],
+ 'body' => 'Hello!'
+ ]);
+ };
+
+This handler returns the same response each time it is invoked. All RingPHP
+handlers must return a ``GuzzleHttp\Ring\Future\FutureArrayInterface``. Use
+``GuzzleHttp\Ring\Future\CompletedFutureArray`` when returning a response that
+has already completed.
+
+Requests
+--------
+
+A request array is a PHP associative array that contains the configuration
+settings need to send a request.
+
+.. code-block:: php
+
+ $request = [
+ 'http_method' => 'GET',
+ 'scheme' => 'http',
+ 'uri' => '/',
+ 'body' => 'hello!',
+ 'client' => ['timeout' => 1.0],
+ 'headers' => [
+ 'host' => ['httpbin.org'],
+ 'X-Foo' => ['baz', 'bar']
+ ]
+ ];
+
+The request array contains the following key value pairs:
+
+request_method
+ (string, required) The HTTP request method, must be all caps corresponding
+ to a HTTP request method, such as ``GET`` or ``POST``.
+
+scheme
+ (string) The transport protocol, must be one of ``http`` or ``https``.
+ Defaults to ``http``.
+
+uri
+ (string, required) The request URI excluding the query string. Must
+ start with "/".
+
+query_string
+ (string) The query string, if present (e.g., ``foo=bar``).
+
+version
+ (string) HTTP protocol version. Defaults to ``1.1``.
+
+headers
+ (required, array) Associative array of headers. Each key represents the
+ header name. Each value contains an array of strings where each entry of
+ the array SHOULD be sent over the wire on a separate header line.
+
+body
+ (string, fopen resource, ``Iterator``, ``GuzzleHttp\Stream\StreamInterface``)
+ The body of the request, if present. Can be a string, resource returned
+ from fopen, an ``Iterator`` that yields chunks of data, an object that
+ implemented ``__toString``, or a ``GuzzleHttp\Stream\StreamInterface``.
+
+future
+ (bool, string) Controls the asynchronous behavior of a response.
+
+ Set to ``true`` or omit the ``future`` option to *request* that a request
+ will be completed asynchronously. Keep in mind that your request might not
+ necessarily be completed asynchronously based on the handler you are using.
+ Set the ``future`` option to ``false`` to request that a synchronous
+ response be provided.
+
+ You can provide a string value to specify fine-tuned future behaviors that
+ may be specific to the underlying handlers you are using. There are,
+ however, some common future options that handlers should implement if
+ possible.
+
+ lazy
+ Requests that the handler does not open and send the request
+ immediately, but rather only opens and sends the request once the
+ future is dereferenced. This option is often useful for sending a large
+ number of requests concurrently to allow handlers to take better
+ advantage of non-blocking transfers by first building up a pool of
+ requests.
+
+ If an handler does not implement or understand a provided string value,
+ then the request MUST be treated as if the user provided ``true`` rather
+ than the string value.
+
+ Future responses created by asynchronous handlers MUST attempt to complete
+ any outstanding future responses when they are destructed. Asynchronous
+ handlers MAY choose to automatically complete responses when the number
+ of outstanding requests reaches an handler-specific threshold.
+
+Client Specific Options
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The following options are only used in ring client handlers.
+
+.. _client-options:
+
+client
+ (array) Associative array of client specific transfer options. The
+ ``client`` request key value pair can contain the following keys:
+
+ cert
+ (string, array) Set to a string to specify the path to a file
+ containing a PEM formatted SSL client side certificate. If a password
+ is required, then set ``cert`` to an array containing the path to the
+ PEM file in the first array element followed by the certificate
+ password in the second array element.
+
+ connect_timeout
+ (float) Float describing the number of seconds to wait while trying to
+ connect to a server. Use ``0`` to wait indefinitely (the default
+ behavior).
+
+ debug
+ (bool, fopen() resource) Set to true or set to a PHP stream returned by
+ fopen() to enable debug output with the handler used to send a request.
+ If set to ``true``, the output is written to PHP's STDOUT. If a PHP
+ ``fopen`` resource handle is provided, the output is written to the
+ stream.
+
+ "Debug output" is handler specific: different handlers will yield
+ different output and various various level of detail. For example, when
+ using cURL to transfer requests, cURL's `CURLOPT_VERBOSE <http://curl.haxx.se/libcurl/c/CURLOPT_VERBOSE.html>`_
+ will be used. When using the PHP stream wrapper, `stream notifications <http://php.net/manual/en/function.stream-notification-callback.php>`_
+ will be emitted.
+
+ decode_content
+ (bool) Specify whether or not ``Content-Encoding`` responses
+ (gzip, deflate, etc.) are automatically decoded. Set to ``true`` to
+ automatically decode encoded responses. Set to ``false`` to not decode
+ responses. By default, content is *not* decoded automatically.
+
+ delay
+ (int) The number of milliseconds to delay before sending the request.
+ This is often used for delaying before retrying a request. Handlers
+ SHOULD implement this if possible, but it is not a strict requirement.
+
+ progress
+ (function) Defines a function to invoke when transfer progress is made.
+ The function accepts the following arguments:
+
+ 1. The total number of bytes expected to be downloaded
+ 2. The number of bytes downloaded so far
+ 3. The number of bytes expected to be uploaded
+ 4. The number of bytes uploaded so far
+
+ proxy
+ (string, array) Pass a string to specify an HTTP proxy, or an
+ associative array to specify different proxies for different protocols
+ where the scheme is the key and the value is the proxy address.
+
+ .. code-block:: php
+
+ $request = [
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['httpbin.org']],
+ 'client' => [
+ // Use different proxies for different URI schemes.
+ 'proxy' => [
+ 'http' => 'http://proxy.example.com:5100',
+ 'https' => 'https://proxy.example.com:6100'
+ ]
+ ]
+ ];
+
+ ssl_key
+ (string, array) Specify the path to a file containing a private SSL key
+ in PEM format. If a password is required, then set to an array
+ containing the path to the SSL key in the first array element followed
+ by the password required for the certificate in the second element.
+
+ save_to
+ (string, fopen resource, ``GuzzleHttp\Stream\StreamInterface``)
+ Specifies where the body of the response is downloaded. Pass a string to
+ open a local file on disk and save the output to the file. Pass an fopen
+ resource to save the output to a PHP stream resource. Pass a
+ ``GuzzleHttp\Stream\StreamInterface`` to save the output to a Guzzle
+ StreamInterface. Omitting this option will typically save the body of a
+ response to a PHP temp stream.
+
+ stream
+ (bool) Set to true to stream a response rather than download it all
+ up-front. This option will only be utilized when the corresponding
+ handler supports it.
+
+ timeout
+ (float) Float describing the timeout of the request in seconds. Use 0 to
+ wait indefinitely (the default behavior).
+
+ verify
+ (bool, string) Describes the SSL certificate verification behavior of a
+ request. Set to true to enable SSL certificate verification using the
+ system CA bundle when available (the default). Set to false to disable
+ certificate verification (this is insecure!). Set to a string to provide
+ the path to a CA bundle on disk to enable verification using a custom
+ certificate.
+
+ version
+ (string) HTTP protocol version to use with the request.
+
+Server Specific Options
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The following options are only used in ring server handlers.
+
+server_port
+ (integer) The port on which the request is being handled. This is only
+ used with ring servers, and is required.
+
+server_name
+ (string) The resolved server name, or the server IP address. Required when
+ using a Ring server.
+
+remote_addr
+ (string) The IP address of the client or the last proxy that sent the
+ request. Required when using a Ring server.
+
+Responses
+---------
+
+A response is an array-like object that implements
+``GuzzleHttp\Ring\Future\FutureArrayInterface``. Responses contain the
+following key value pairs:
+
+body
+ (string, fopen resource, ``Iterator``, ``GuzzleHttp\Stream\StreamInterface``)
+ The body of the response, if present. Can be a string, resource returned
+ from fopen, an ``Iterator`` that yields chunks of data, an object that
+ implemented ``__toString``, or a ``GuzzleHttp\Stream\StreamInterface``.
+
+effective_url
+ (string) The URL that returned the resulting response.
+
+error
+ (``\Exception``) Contains an exception describing any errors that were
+ encountered during the transfer.
+
+headers
+ (Required, array) Associative array of headers. Each key represents the
+ header name. Each value contains an array of strings where each entry of
+ the array is a header line. The headers array MAY be an empty array in the
+ event an error occurred before a response was received.
+
+reason
+ (string) Optional reason phrase. This option should be provided when the
+ reason phrase does not match the typical reason phrase associated with the
+ ``status`` code. See `RFC 7231 <http://tools.ietf.org/html/rfc7231#section-6.1>`_
+ for a list of HTTP reason phrases mapped to status codes.
+
+status
+ (Required, integer) The HTTP status code. The status code MAY be set to
+ ``null`` in the event an error occurred before a response was received
+ (e.g., a networking error).
+
+transfer_stats
+ (array) Provides an associative array of arbitrary transfer statistics if
+ provided by the underlying handler.
+
+version
+ (string) HTTP protocol version. Defaults to ``1.1``.
+
+Middleware
+----------
+
+Ring middleware augments the functionality of handlers by invoking them in the
+process of generating responses. Middleware is typically implemented as a
+higher-order function that takes one or more handlers as arguments followed by
+an optional associative array of options as the last argument, returning a new
+handler with the desired compound behavior.
+
+Here's an example of a middleware that adds a Content-Type header to each
+request.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\CurlHandler;
+ use GuzzleHttp\Ring\Core;
+
+ $contentTypeHandler = function(callable $handler, $contentType) {
+ return function (array $request) use ($handler, $contentType) {
+ return $handler(Core::setHeader('Content-Type', $contentType));
+ };
+ };
+
+ $baseHandler = new CurlHandler();
+ $wrappedHandler = $contentTypeHandler($baseHandler, 'text/html');
+ $response = $wrappedHandler([/** request hash **/]);
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/docs/testing.rst b/www/wiki/vendor/guzzlehttp/ringphp/docs/testing.rst
new file mode 100644
index 00000000..9df2562e
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/docs/testing.rst
@@ -0,0 +1,74 @@
+=======
+Testing
+=======
+
+RingPHP tests client handlers using `PHPUnit <https://phpunit.de/>`_ and a
+built-in node.js web server.
+
+Running Tests
+-------------
+
+First, install the dependencies using `Composer <https://getcomposer.org>`_.
+
+ composer.phar install
+
+Next, run the unit tests using ``Make``.
+
+ make test
+
+The tests are also run on Travis-CI on each commit: https://travis-ci.org/guzzle/guzzle-ring
+
+Test Server
+-----------
+
+Testing client handlers usually involves actually sending HTTP requests.
+RingPHP provides a node.js web server that returns canned responses and
+keep a list of the requests that have been received. The server can then
+be queried to get a list of the requests that were sent by the client so that
+you can ensure that the client serialized and transferred requests as intended.
+
+The server keeps a list of queued responses and returns responses that are
+popped off of the queue as HTTP requests are received. When there are not
+more responses to serve, the server returns a 500 error response.
+
+The test server uses the ``GuzzleHttp\Tests\Ring\Client\Server`` class to
+control the server.
+
+.. code-block:: php
+
+ use GuzzleHttp\Ring\Client\StreamHandler;
+ use GuzzleHttp\Tests\Ring\Client\Server;
+
+ // First return a 200 followed by a 404 response.
+ Server::enqueue([
+ ['status' => 200],
+ ['status' => 404]
+ ]);
+
+ $handler = new StreamHandler();
+
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'uri' => '/'
+ ]);
+
+ assert(200 == $response['status']);
+
+ $response = $handler([
+ 'http_method' => 'HEAD',
+ 'headers' => ['host' => [Server::$host]],
+ 'uri' => '/'
+ ]);
+
+ assert(404 == $response['status']);
+
+After requests have been sent, you can get a list of the requests as they
+were sent over the wire to ensure they were sent correctly.
+
+.. code-block:: php
+
+ $received = Server::received();
+
+ assert('GET' == $received[0]['http_method']);
+ assert('HEAD' == $received[1]['http_method']);
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/phpunit.xml.dist b/www/wiki/vendor/guzzlehttp/ringphp/phpunit.xml.dist
new file mode 100644
index 00000000..1d192902
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/phpunit.xml.dist
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit bootstrap="./tests/bootstrap.php"
+ colors="true">
+ <testsuites>
+ <testsuite>
+ <directory>tests</directory>
+ </testsuite>
+ </testsuites>
+ <filter>
+ <whitelist>
+ <directory suffix=".php">src</directory>
+ </whitelist>
+ </filter>
+</phpunit>
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Client/ClientUtils.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Client/ClientUtils.php
new file mode 100644
index 00000000..27d5fe7e
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Client/ClientUtils.php
@@ -0,0 +1,74 @@
+<?php
+namespace GuzzleHttp\Ring\Client;
+
+/**
+ * Client specific utility functions.
+ */
+class ClientUtils
+{
+ /**
+ * 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.
+ */
+ public static function getDefaultCaBundle()
+ {
+ 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',
+ // 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(self::CA_ERR);
+ }
+
+ const CA_ERR = "
+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/5.3/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.";
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Client/CurlFactory.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Client/CurlFactory.php
new file mode 100644
index 00000000..2c9eb684
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Client/CurlFactory.php
@@ -0,0 +1,560 @@
+<?php
+namespace GuzzleHttp\Ring\Client;
+
+use GuzzleHttp\Ring\Core;
+use GuzzleHttp\Ring\Exception\ConnectException;
+use GuzzleHttp\Ring\Exception\RingException;
+use GuzzleHttp\Stream\LazyOpenStream;
+use GuzzleHttp\Stream\StreamInterface;
+
+/**
+ * Creates curl resources from a request
+ */
+class CurlFactory
+{
+ /**
+ * Creates a cURL handle, header resource, and body resource based on a
+ * transaction.
+ *
+ * @param array $request Request hash
+ * @param null|resource $handle Optionally provide a curl handle to modify
+ *
+ * @return array Returns an array of the curl handle, headers array, and
+ * response body handle.
+ * @throws \RuntimeException when an option cannot be applied
+ */
+ public function __invoke(array $request, $handle = null)
+ {
+ $headers = [];
+ $options = $this->getDefaultOptions($request, $headers);
+ $this->applyMethod($request, $options);
+
+ if (isset($request['client'])) {
+ $this->applyHandlerOptions($request, $options);
+ }
+
+ $this->applyHeaders($request, $options);
+ unset($options['_headers']);
+
+ // Add handler options from the request's configuration options
+ if (isset($request['client']['curl'])) {
+ $options = $this->applyCustomCurlOptions(
+ $request['client']['curl'],
+ $options
+ );
+ }
+
+ if (!$handle) {
+ $handle = curl_init();
+ }
+
+ $body = $this->getOutputBody($request, $options);
+ curl_setopt_array($handle, $options);
+
+ return [$handle, &$headers, $body];
+ }
+
+ /**
+ * Creates a response hash from a cURL result.
+ *
+ * @param callable $handler Handler that was used.
+ * @param array $request Request that sent.
+ * @param array $response Response hash to update.
+ * @param array $headers Headers received during transfer.
+ * @param resource $body Body fopen response.
+ *
+ * @return array
+ */
+ public static function createResponse(
+ callable $handler,
+ array $request,
+ array $response,
+ array $headers,
+ $body
+ ) {
+ if (isset($response['transfer_stats']['url'])) {
+ $response['effective_url'] = $response['transfer_stats']['url'];
+ }
+
+ if (!empty($headers)) {
+ $startLine = explode(' ', array_shift($headers), 3);
+ $headerList = Core::headersFromLines($headers);
+ $response['headers'] = $headerList;
+ $response['version'] = isset($startLine[0]) ? substr($startLine[0], 5) : null;
+ $response['status'] = isset($startLine[1]) ? (int) $startLine[1] : null;
+ $response['reason'] = isset($startLine[2]) ? $startLine[2] : null;
+ $response['body'] = $body;
+ Core::rewindBody($response);
+ }
+
+ return !empty($response['curl']['errno']) || !isset($response['status'])
+ ? self::createErrorResponse($handler, $request, $response)
+ : $response;
+ }
+
+ private static function createErrorResponse(
+ callable $handler,
+ array $request,
+ array $response
+ ) {
+ static $connectionErrors = [
+ CURLE_OPERATION_TIMEOUTED => true,
+ CURLE_COULDNT_RESOLVE_HOST => true,
+ CURLE_COULDNT_CONNECT => true,
+ CURLE_SSL_CONNECT_ERROR => true,
+ CURLE_GOT_NOTHING => true,
+ ];
+
+ // Retry when nothing is present or when curl failed to rewind.
+ if (!isset($response['err_message'])
+ && (empty($response['curl']['errno'])
+ || $response['curl']['errno'] == 65)
+ ) {
+ return self::retryFailedRewind($handler, $request, $response);
+ }
+
+ $message = isset($response['err_message'])
+ ? $response['err_message']
+ : sprintf('cURL error %s: %s',
+ $response['curl']['errno'],
+ isset($response['curl']['error'])
+ ? $response['curl']['error']
+ : 'See http://curl.haxx.se/libcurl/c/libcurl-errors.html');
+
+ $error = isset($response['curl']['errno'])
+ && isset($connectionErrors[$response['curl']['errno']])
+ ? new ConnectException($message)
+ : new RingException($message);
+
+ return $response + [
+ 'status' => null,
+ 'reason' => null,
+ 'body' => null,
+ 'headers' => [],
+ 'error' => $error,
+ ];
+ }
+
+ private function getOutputBody(array $request, array &$options)
+ {
+ // Determine where the body of the response (if any) will be streamed.
+ if (isset($options[CURLOPT_WRITEFUNCTION])) {
+ return $request['client']['save_to'];
+ }
+
+ if (isset($options[CURLOPT_FILE])) {
+ return $options[CURLOPT_FILE];
+ }
+
+ if ($request['http_method'] != 'HEAD') {
+ // Create a default body if one was not provided
+ return $options[CURLOPT_FILE] = fopen('php://temp', 'w+');
+ }
+
+ return null;
+ }
+
+ private function getDefaultOptions(array $request, array &$headers)
+ {
+ $url = Core::url($request);
+ $startingResponse = false;
+
+ $options = [
+ '_headers' => $request['headers'],
+ CURLOPT_CUSTOMREQUEST => $request['http_method'],
+ CURLOPT_URL => $url,
+ CURLOPT_RETURNTRANSFER => false,
+ CURLOPT_HEADER => false,
+ CURLOPT_CONNECTTIMEOUT => 150,
+ CURLOPT_HEADERFUNCTION => function ($ch, $h) use (&$headers, &$startingResponse) {
+ $value = trim($h);
+ if ($value === '') {
+ $startingResponse = true;
+ } elseif ($startingResponse) {
+ $startingResponse = false;
+ $headers = [$value];
+ } else {
+ $headers[] = $value;
+ }
+ return strlen($h);
+ },
+ ];
+
+ if (isset($request['version'])) {
+ if ($request['version'] == 2.0) {
+ $options[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0;
+ } else if ($request['version'] == 1.1) {
+ $options[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
+ } else {
+ $options[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0;
+ }
+ }
+
+ if (defined('CURLOPT_PROTOCOLS')) {
+ $options[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
+ }
+
+ return $options;
+ }
+
+ private function applyMethod(array $request, array &$options)
+ {
+ if (isset($request['body'])) {
+ $this->applyBody($request, $options);
+ return;
+ }
+
+ switch ($request['http_method']) {
+ case 'PUT':
+ case 'POST':
+ // See http://tools.ietf.org/html/rfc7230#section-3.3.2
+ if (!Core::hasHeader($request, 'Content-Length')) {
+ $options[CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
+ }
+ break;
+ case 'HEAD':
+ $options[CURLOPT_NOBODY] = true;
+ unset(
+ $options[CURLOPT_WRITEFUNCTION],
+ $options[CURLOPT_READFUNCTION],
+ $options[CURLOPT_FILE],
+ $options[CURLOPT_INFILE]
+ );
+ }
+ }
+
+ private function applyBody(array $request, array &$options)
+ {
+ $contentLength = Core::firstHeader($request, 'Content-Length');
+ $size = $contentLength !== null ? (int) $contentLength : null;
+
+ // Send the body as a string if the size is less than 1MB OR if the
+ // [client][curl][body_as_string] request value is set.
+ if (($size !== null && $size < 1000000) ||
+ isset($request['client']['curl']['body_as_string']) ||
+ is_string($request['body'])
+ ) {
+ $options[CURLOPT_POSTFIELDS] = Core::body($request);
+ // Don't duplicate the Content-Length header
+ $this->removeHeader('Content-Length', $options);
+ $this->removeHeader('Transfer-Encoding', $options);
+ } else {
+ $options[CURLOPT_UPLOAD] = true;
+ if ($size !== null) {
+ // Let cURL handle setting the Content-Length header
+ $options[CURLOPT_INFILESIZE] = $size;
+ $this->removeHeader('Content-Length', $options);
+ }
+ $this->addStreamingBody($request, $options);
+ }
+
+ // If the Expect header is not present, prevent curl from adding it
+ if (!Core::hasHeader($request, 'Expect')) {
+ $options[CURLOPT_HTTPHEADER][] = 'Expect:';
+ }
+
+ // cURL sometimes adds a content-type by default. Prevent this.
+ if (!Core::hasHeader($request, 'Content-Type')) {
+ $options[CURLOPT_HTTPHEADER][] = 'Content-Type:';
+ }
+ }
+
+ private function addStreamingBody(array $request, array &$options)
+ {
+ $body = $request['body'];
+
+ if ($body instanceof StreamInterface) {
+ $options[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) {
+ return (string) $body->read($length);
+ };
+ if (!isset($options[CURLOPT_INFILESIZE])) {
+ if ($size = $body->getSize()) {
+ $options[CURLOPT_INFILESIZE] = $size;
+ }
+ }
+ } elseif (is_resource($body)) {
+ $options[CURLOPT_INFILE] = $body;
+ } elseif ($body instanceof \Iterator) {
+ $buf = '';
+ $options[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body, &$buf) {
+ if ($body->valid()) {
+ $buf .= $body->current();
+ $body->next();
+ }
+ $result = (string) substr($buf, 0, $length);
+ $buf = substr($buf, $length);
+ return $result;
+ };
+ } else {
+ throw new \InvalidArgumentException('Invalid request body provided');
+ }
+ }
+
+ private function applyHeaders(array $request, array &$options)
+ {
+ foreach ($options['_headers'] as $name => $values) {
+ foreach ($values as $value) {
+ $options[CURLOPT_HTTPHEADER][] = "$name: $value";
+ }
+ }
+
+ // Remove the Accept header if one was not set
+ if (!Core::hasHeader($request, 'Accept')) {
+ $options[CURLOPT_HTTPHEADER][] = 'Accept:';
+ }
+ }
+
+ /**
+ * Takes an array of curl options specified in the 'curl' option of a
+ * request's configuration array and maps them to CURLOPT_* options.
+ *
+ * This method is only called when a request has a 'curl' config setting.
+ *
+ * @param array $config Configuration array of custom curl option
+ * @param array $options Array of existing curl options
+ *
+ * @return array Returns a new array of curl options
+ */
+ private function applyCustomCurlOptions(array $config, array $options)
+ {
+ $curlOptions = [];
+ foreach ($config as $key => $value) {
+ if (is_int($key)) {
+ $curlOptions[$key] = $value;
+ }
+ }
+
+ return $curlOptions + $options;
+ }
+
+ /**
+ * 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;
+ }
+ }
+ }
+
+ /**
+ * Applies an array of request client options to a the options array.
+ *
+ * This method uses a large switch rather than double-dispatch to save on
+ * high overhead of calling functions in PHP.
+ */
+ private function applyHandlerOptions(array $request, array &$options)
+ {
+ foreach ($request['client'] as $key => $value) {
+ switch ($key) {
+ // Violating PSR-4 to provide more room.
+ case 'verify':
+
+ if ($value === false) {
+ unset($options[CURLOPT_CAINFO]);
+ $options[CURLOPT_SSL_VERIFYHOST] = 0;
+ $options[CURLOPT_SSL_VERIFYPEER] = false;
+ continue 2;
+ }
+
+ $options[CURLOPT_SSL_VERIFYHOST] = 2;
+ $options[CURLOPT_SSL_VERIFYPEER] = true;
+
+ if (is_string($value)) {
+ $options[CURLOPT_CAINFO] = $value;
+ if (!file_exists($value)) {
+ throw new \InvalidArgumentException(
+ "SSL CA bundle not found: $value"
+ );
+ }
+ }
+ break;
+
+ case 'decode_content':
+
+ if ($value === false) {
+ continue 2;
+ }
+
+ $accept = Core::firstHeader($request, 'Accept-Encoding');
+ if ($accept) {
+ $options[CURLOPT_ENCODING] = $accept;
+ } else {
+ $options[CURLOPT_ENCODING] = '';
+ // Don't let curl send the header over the wire
+ $options[CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
+ }
+ break;
+
+ case 'save_to':
+
+ if (is_string($value)) {
+ if (!is_dir(dirname($value))) {
+ throw new \RuntimeException(sprintf(
+ 'Directory %s does not exist for save_to value of %s',
+ dirname($value),
+ $value
+ ));
+ }
+ $value = new LazyOpenStream($value, 'w+');
+ }
+
+ if ($value instanceof StreamInterface) {
+ $options[CURLOPT_WRITEFUNCTION] =
+ function ($ch, $write) use ($value) {
+ return $value->write($write);
+ };
+ } elseif (is_resource($value)) {
+ $options[CURLOPT_FILE] = $value;
+ } else {
+ throw new \InvalidArgumentException('save_to must be a '
+ . 'GuzzleHttp\Stream\StreamInterface or resource');
+ }
+ break;
+
+ case 'timeout':
+
+ if (defined('CURLOPT_TIMEOUT_MS')) {
+ $options[CURLOPT_TIMEOUT_MS] = $value * 1000;
+ } else {
+ $options[CURLOPT_TIMEOUT] = $value;
+ }
+ break;
+
+ case 'connect_timeout':
+
+ if (defined('CURLOPT_CONNECTTIMEOUT_MS')) {
+ $options[CURLOPT_CONNECTTIMEOUT_MS] = $value * 1000;
+ } else {
+ $options[CURLOPT_CONNECTTIMEOUT] = $value;
+ }
+ break;
+
+ case 'proxy':
+
+ if (!is_array($value)) {
+ $options[CURLOPT_PROXY] = $value;
+ } elseif (isset($request['scheme'])) {
+ $scheme = $request['scheme'];
+ if (isset($value[$scheme])) {
+ $options[CURLOPT_PROXY] = $value[$scheme];
+ }
+ }
+ break;
+
+ case 'cert':
+
+ if (is_array($value)) {
+ $options[CURLOPT_SSLCERTPASSWD] = $value[1];
+ $value = $value[0];
+ }
+
+ if (!file_exists($value)) {
+ throw new \InvalidArgumentException(
+ "SSL certificate not found: {$value}"
+ );
+ }
+
+ $options[CURLOPT_SSLCERT] = $value;
+ break;
+
+ case 'ssl_key':
+
+ if (is_array($value)) {
+ $options[CURLOPT_SSLKEYPASSWD] = $value[1];
+ $value = $value[0];
+ }
+
+ if (!file_exists($value)) {
+ throw new \InvalidArgumentException(
+ "SSL private key not found: {$value}"
+ );
+ }
+
+ $options[CURLOPT_SSLKEY] = $value;
+ break;
+
+ case 'progress':
+
+ if (!is_callable($value)) {
+ throw new \InvalidArgumentException(
+ 'progress client option must be callable'
+ );
+ }
+
+ $options[CURLOPT_NOPROGRESS] = false;
+ $options[CURLOPT_PROGRESSFUNCTION] =
+ function () use ($value) {
+ $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($value, $args);
+ };
+ break;
+
+ case 'debug':
+
+ if ($value) {
+ $options[CURLOPT_STDERR] = Core::getDebugResource($value);
+ $options[CURLOPT_VERBOSE] = true;
+ }
+ break;
+ }
+ }
+ }
+
+ /**
+ * 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,
+ array $request,
+ array $response
+ ) {
+ // If there is no body, then there is some other kind of issue. This
+ // is weird and should probably never happen.
+ if (!isset($request['body'])) {
+ $response['err_message'] = 'No response was received for a request '
+ . 'with no body. This could mean that you are saturating your '
+ . 'network.';
+ return self::createErrorResponse($handler, $request, $response);
+ }
+
+ if (!Core::rewindBody($request)) {
+ $response['err_message'] = 'The connection unexpectedly failed '
+ . 'without providing an error. The request would have been '
+ . 'retried, but attempting to rewind the request body failed.';
+ return self::createErrorResponse($handler, $request, $response);
+ }
+
+ // Retry no more than 3 times before giving up.
+ if (!isset($request['curl']['retries'])) {
+ $request['curl']['retries'] = 1;
+ } elseif ($request['curl']['retries'] == 2) {
+ $response['err_message'] = 'The cURL request was retried 3 times '
+ . 'and did no succeed. 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::createErrorResponse($handler, $request, $response);
+ } else {
+ $request['curl']['retries']++;
+ }
+
+ return $handler($request);
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Client/CurlHandler.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Client/CurlHandler.php
new file mode 100644
index 00000000..e00aa4ea
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Client/CurlHandler.php
@@ -0,0 +1,135 @@
+<?php
+namespace GuzzleHttp\Ring\Client;
+
+use GuzzleHttp\Ring\Future\CompletedFutureArray;
+use GuzzleHttp\Ring\Core;
+
+/**
+ * HTTP handler that uses cURL easy handles as a transport layer.
+ *
+ * Requires PHP 5.5+
+ *
+ * When using the CurlHandler, custom curl options can be specified as an
+ * associative array of curl option constants mapping to values in the
+ * **curl** key of the "client" key of the request.
+ */
+class CurlHandler
+{
+ /** @var callable */
+ private $factory;
+
+ /** @var array Array of curl easy handles */
+ private $handles = [];
+
+ /** @var array Array of owned curl easy handles */
+ private $ownedHandles = [];
+
+ /** @var int Total number of idle handles to keep in cache */
+ private $maxHandles;
+
+ /**
+ * Accepts an associative array of options:
+ *
+ * - factory: Optional callable factory used to create cURL handles.
+ * The callable is passed a request hash when invoked, and returns an
+ * array of the curl handle, headers resource, and body resource.
+ * - max_handles: Maximum number of idle handles (defaults to 5).
+ *
+ * @param array $options Array of options to use with the handler
+ */
+ public function __construct(array $options = [])
+ {
+ $this->handles = $this->ownedHandles = [];
+ $this->factory = isset($options['handle_factory'])
+ ? $options['handle_factory']
+ : new CurlFactory();
+ $this->maxHandles = isset($options['max_handles'])
+ ? $options['max_handles']
+ : 5;
+ }
+
+ public function __destruct()
+ {
+ foreach ($this->handles as $handle) {
+ if (is_resource($handle)) {
+ curl_close($handle);
+ }
+ }
+ }
+
+ /**
+ * @param array $request
+ *
+ * @return CompletedFutureArray
+ */
+ public function __invoke(array $request)
+ {
+ return new CompletedFutureArray(
+ $this->_invokeAsArray($request)
+ );
+ }
+
+ /**
+ * @internal
+ *
+ * @param array $request
+ *
+ * @return array
+ */
+ public function _invokeAsArray(array $request)
+ {
+ $factory = $this->factory;
+
+ // Ensure headers are by reference. They're updated elsewhere.
+ $result = $factory($request, $this->checkoutEasyHandle());
+ $h = $result[0];
+ $hd =& $result[1];
+ $bd = $result[2];
+ Core::doSleep($request);
+ curl_exec($h);
+ $response = ['transfer_stats' => curl_getinfo($h)];
+ $response['curl']['error'] = curl_error($h);
+ $response['curl']['errno'] = curl_errno($h);
+ $response['transfer_stats'] = array_merge($response['transfer_stats'], $response['curl']);
+ $this->releaseEasyHandle($h);
+
+ return CurlFactory::createResponse([$this, '_invokeAsArray'], $request, $response, $hd, $bd);
+ }
+
+ private function checkoutEasyHandle()
+ {
+ // Find an unused handle in the cache
+ if (false !== ($key = array_search(false, $this->ownedHandles, true))) {
+ $this->ownedHandles[$key] = true;
+ return $this->handles[$key];
+ }
+
+ // Add a new handle
+ $handle = curl_init();
+ $id = (int) $handle;
+ $this->handles[$id] = $handle;
+ $this->ownedHandles[$id] = true;
+
+ return $handle;
+ }
+
+ private function releaseEasyHandle($handle)
+ {
+ $id = (int) $handle;
+ if (count($this->ownedHandles) > $this->maxHandles) {
+ curl_close($this->handles[$id]);
+ unset($this->handles[$id], $this->ownedHandles[$id]);
+ } else {
+ // curl_reset doesn't clear these out for some reason
+ static $unsetValues = [
+ CURLOPT_HEADERFUNCTION => null,
+ CURLOPT_WRITEFUNCTION => null,
+ CURLOPT_READFUNCTION => null,
+ CURLOPT_PROGRESSFUNCTION => null,
+ ];
+ curl_setopt_array($handle, $unsetValues);
+ curl_reset($handle);
+ $this->ownedHandles[$id] = false;
+ }
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Client/CurlMultiHandler.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Client/CurlMultiHandler.php
new file mode 100644
index 00000000..f84cf199
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Client/CurlMultiHandler.php
@@ -0,0 +1,248 @@
+<?php
+namespace GuzzleHttp\Ring\Client;
+
+use GuzzleHttp\Ring\Future\FutureArray;
+use React\Promise\Deferred;
+
+/**
+ * Returns an asynchronous response using curl_multi_* functions.
+ *
+ * This handler supports future responses and the "delay" request client
+ * option that can be used to delay before sending a request.
+ *
+ * When using the CurlMultiHandler, custom curl options can be specified as an
+ * associative array of curl option constants mapping to values in the
+ * **curl** key of the "client" key of the request.
+ *
+ * @property resource $_mh Internal use only. Lazy loaded multi-handle.
+ */
+class CurlMultiHandler
+{
+ /** @var callable */
+ private $factory;
+ private $selectTimeout;
+ private $active;
+ private $handles = [];
+ private $delays = [];
+ private $maxHandles;
+
+ /**
+ * This handler accepts the following options:
+ *
+ * - mh: An optional curl_multi resource
+ * - handle_factory: An optional callable used to generate curl handle
+ * resources. the callable accepts a request hash and returns an array
+ * of the handle, headers file resource, and the body resource.
+ * - select_timeout: Optional timeout (in seconds) to block before timing
+ * out while selecting curl handles. Defaults to 1 second.
+ * - max_handles: Optional integer representing the maximum number of
+ * open requests. When this number is reached, the queued futures are
+ * flushed.
+ *
+ * @param array $options
+ */
+ public function __construct(array $options = [])
+ {
+ if (isset($options['mh'])) {
+ $this->_mh = $options['mh'];
+ }
+ $this->factory = isset($options['handle_factory'])
+ ? $options['handle_factory'] : new CurlFactory();
+ $this->selectTimeout = isset($options['select_timeout'])
+ ? $options['select_timeout'] : 1;
+ $this->maxHandles = isset($options['max_handles'])
+ ? $options['max_handles'] : 100;
+ }
+
+ public function __get($name)
+ {
+ if ($name === '_mh') {
+ return $this->_mh = curl_multi_init();
+ }
+
+ throw new \BadMethodCallException();
+ }
+
+ public function __destruct()
+ {
+ // Finish any open connections before terminating the script.
+ if ($this->handles) {
+ $this->execute();
+ }
+
+ if (isset($this->_mh)) {
+ curl_multi_close($this->_mh);
+ unset($this->_mh);
+ }
+ }
+
+ public function __invoke(array $request)
+ {
+ $factory = $this->factory;
+ $result = $factory($request);
+ $entry = [
+ 'request' => $request,
+ 'response' => [],
+ 'handle' => $result[0],
+ 'headers' => &$result[1],
+ 'body' => $result[2],
+ 'deferred' => new Deferred(),
+ ];
+
+ $id = (int) $result[0];
+
+ $future = new FutureArray(
+ $entry['deferred']->promise(),
+ [$this, 'execute'],
+ function () use ($id) {
+ return $this->cancel($id);
+ }
+ );
+
+ $this->addRequest($entry);
+
+ // Transfer outstanding requests if there are too many open handles.
+ if (count($this->handles) >= $this->maxHandles) {
+ $this->execute();
+ }
+
+ return $future;
+ }
+
+ /**
+ * Runs until all outstanding connections have completed.
+ */
+ public function execute()
+ {
+ do {
+
+ 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);
+ }
+
+ // Add any delayed futures if needed.
+ if ($this->delays) {
+ $this->addDelays();
+ }
+
+ do {
+ $mrc = curl_multi_exec($this->_mh, $this->active);
+ } while ($mrc === CURLM_CALL_MULTI_PERFORM);
+
+ $this->processMessages();
+
+ // If there are delays but no transfers, then sleep for a bit.
+ if (!$this->active && $this->delays) {
+ usleep(500);
+ }
+
+ } while ($this->active || $this->handles);
+ }
+
+ private function addRequest(array &$entry)
+ {
+ $id = (int) $entry['handle'];
+ $this->handles[$id] = $entry;
+
+ // If the request is a delay, then add the reques to the curl multi
+ // pool only after the specified delay.
+ if (isset($entry['request']['client']['delay'])) {
+ $this->delays[$id] = microtime(true) + ($entry['request']['client']['delay'] / 1000);
+ } elseif (empty($entry['request']['future'])) {
+ curl_multi_add_handle($this->_mh, $entry['handle']);
+ } else {
+ curl_multi_add_handle($this->_mh, $entry['handle']);
+ // "lazy" futures are only sent once the pool has many requests.
+ if ($entry['request']['future'] !== 'lazy') {
+ do {
+ $mrc = curl_multi_exec($this->_mh, $this->active);
+ } while ($mrc === CURLM_CALL_MULTI_PERFORM);
+ $this->processMessages();
+ }
+ }
+ }
+
+ private function removeProcessed($id)
+ {
+ if (isset($this->handles[$id])) {
+ curl_multi_remove_handle(
+ $this->_mh,
+ $this->handles[$id]['handle']
+ );
+ curl_close($this->handles[$id]['handle']);
+ unset($this->handles[$id], $this->delays[$id]);
+ }
+ }
+
+ /**
+ * 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]['handle'];
+ unset($this->delays[$id], $this->handles[$id]);
+ curl_multi_remove_handle($this->_mh, $handle);
+ curl_close($handle);
+
+ return true;
+ }
+
+ private function addDelays()
+ {
+ $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]['handle']
+ );
+ }
+ }
+ }
+
+ private function processMessages()
+ {
+ while ($done = curl_multi_info_read($this->_mh)) {
+ $id = (int) $done['handle'];
+
+ if (!isset($this->handles[$id])) {
+ // Probably was cancelled.
+ continue;
+ }
+
+ $entry = $this->handles[$id];
+ $entry['response']['transfer_stats'] = curl_getinfo($done['handle']);
+
+ if ($done['result'] !== CURLM_OK) {
+ $entry['response']['curl']['errno'] = $done['result'];
+ $entry['response']['curl']['error'] = curl_error($done['handle']);
+ }
+
+ $result = CurlFactory::createResponse(
+ $this,
+ $entry['request'],
+ $entry['response'],
+ $entry['headers'],
+ $entry['body']
+ );
+
+ $this->removeProcessed($id);
+ $entry['deferred']->resolve($result);
+ }
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Client/Middleware.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Client/Middleware.php
new file mode 100644
index 00000000..6fa7318a
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Client/Middleware.php
@@ -0,0 +1,58 @@
+<?php
+namespace GuzzleHttp\Ring\Client;
+
+/**
+ * Provides basic middleware wrappers.
+ *
+ * If a middleware is more complex than a few lines of code, then it should
+ * be implemented in a class rather than a static method.
+ */
+class Middleware
+{
+ /**
+ * Sends future requests to a future compatible handler while sending all
+ * other requests to a default handler.
+ *
+ * When the "future" option is not provided on a request, any future responses
+ * are automatically converted to synchronous responses and block.
+ *
+ * @param callable $default Handler used for non-streaming responses
+ * @param callable $future Handler used for future responses
+ *
+ * @return callable Returns the composed handler.
+ */
+ public static function wrapFuture(
+ callable $default,
+ callable $future
+ ) {
+ return function (array $request) use ($default, $future) {
+ return empty($request['client']['future'])
+ ? $default($request)
+ : $future($request);
+ };
+ }
+
+ /**
+ * Sends streaming requests to a streaming compatible handler while sendin
+ * all other requests to a default handler.
+ *
+ * This, for example, could be useful for taking advantage of the
+ * performance benefits of curl while still supporting true streaming
+ * through the StreamHandler.
+ *
+ * @param callable $default Handler used for non-streaming responses
+ * @param callable $streaming Handler used for streaming responses
+ *
+ * @return callable Returns the composed handler.
+ */
+ public static function wrapStreaming(
+ callable $default,
+ callable $streaming
+ ) {
+ return function (array $request) use ($default, $streaming) {
+ return empty($request['client']['stream'])
+ ? $default($request)
+ : $streaming($request);
+ };
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Client/MockHandler.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Client/MockHandler.php
new file mode 100644
index 00000000..56cc32da
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Client/MockHandler.php
@@ -0,0 +1,52 @@
+<?php
+namespace GuzzleHttp\Ring\Client;
+
+use GuzzleHttp\Ring\Core;
+use GuzzleHttp\Ring\Future\CompletedFutureArray;
+use GuzzleHttp\Ring\Future\FutureArrayInterface;
+
+/**
+ * Ring handler that returns a canned response or evaluated function result.
+ */
+class MockHandler
+{
+ /** @var callable|array|FutureArrayInterface */
+ private $result;
+
+ /**
+ * Provide an array or future to always return the same value. Provide a
+ * callable that accepts a request object and returns an array or future
+ * to dynamically create a response.
+ *
+ * @param array|FutureArrayInterface|callable $result Mock return value.
+ */
+ public function __construct($result)
+ {
+ $this->result = $result;
+ }
+
+ public function __invoke(array $request)
+ {
+ Core::doSleep($request);
+ $response = is_callable($this->result)
+ ? call_user_func($this->result, $request)
+ : $this->result;
+
+ if (is_array($response)) {
+ $response = new CompletedFutureArray($response + [
+ 'status' => null,
+ 'body' => null,
+ 'headers' => [],
+ 'reason' => null,
+ 'effective_url' => null,
+ ]);
+ } elseif (!$response instanceof FutureArrayInterface) {
+ throw new \InvalidArgumentException(
+ 'Response must be an array or FutureArrayInterface. Found '
+ . Core::describeType($request)
+ );
+ }
+
+ return $response;
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Client/StreamHandler.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Client/StreamHandler.php
new file mode 100644
index 00000000..4bacec13
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Client/StreamHandler.php
@@ -0,0 +1,414 @@
+<?php
+namespace GuzzleHttp\Ring\Client;
+
+use GuzzleHttp\Ring\Core;
+use GuzzleHttp\Ring\Exception\ConnectException;
+use GuzzleHttp\Ring\Exception\RingException;
+use GuzzleHttp\Ring\Future\CompletedFutureArray;
+use GuzzleHttp\Stream\InflateStream;
+use GuzzleHttp\Stream\StreamInterface;
+use GuzzleHttp\Stream\Stream;
+use GuzzleHttp\Stream\Utils;
+
+/**
+ * RingPHP client handler that uses PHP's HTTP stream wrapper.
+ */
+class StreamHandler
+{
+ private $options;
+ private $lastHeaders;
+
+ public function __construct(array $options = [])
+ {
+ $this->options = $options;
+ }
+
+ public function __invoke(array $request)
+ {
+ $url = Core::url($request);
+ Core::doSleep($request);
+
+ try {
+ // Does not support the expect header.
+ $request = Core::removeHeader($request, 'Expect');
+ $stream = $this->createStream($url, $request);
+ return $this->createResponse($request, $url, $stream);
+ } catch (RingException $e) {
+ return $this->createErrorResponse($url, $e);
+ }
+ }
+
+ private function createResponse(array $request, $url, $stream)
+ {
+ $hdrs = $this->lastHeaders;
+ $this->lastHeaders = null;
+ $parts = explode(' ', array_shift($hdrs), 3);
+ $response = [
+ 'version' => substr($parts[0], 5),
+ 'status' => $parts[1],
+ 'reason' => isset($parts[2]) ? $parts[2] : null,
+ 'headers' => Core::headersFromLines($hdrs),
+ 'effective_url' => $url,
+ ];
+
+ $stream = $this->checkDecode($request, $response, $stream);
+
+ // If not streaming, then drain the response into a stream.
+ if (empty($request['client']['stream'])) {
+ $dest = isset($request['client']['save_to'])
+ ? $request['client']['save_to']
+ : fopen('php://temp', 'r+');
+ $stream = $this->drain($stream, $dest);
+ }
+
+ $response['body'] = $stream;
+
+ return new CompletedFutureArray($response);
+ }
+
+ private function checkDecode(array $request, array $response, $stream)
+ {
+ // Automatically decode responses when instructed.
+ if (!empty($request['client']['decode_content'])) {
+ switch (Core::firstHeader($response, 'Content-Encoding', true)) {
+ case 'gzip':
+ case 'deflate':
+ $stream = new InflateStream(Stream::factory($stream));
+ break;
+ }
+ }
+
+ return $stream;
+ }
+
+ /**
+ * Drains the stream into the "save_to" client option.
+ *
+ * @param resource $stream
+ * @param string|resource|StreamInterface $dest
+ *
+ * @return Stream
+ * @throws \RuntimeException when the save_to option is invalid.
+ */
+ private function drain($stream, $dest)
+ {
+ if (is_resource($stream)) {
+ if (!is_resource($dest)) {
+ $stream = Stream::factory($stream);
+ } else {
+ stream_copy_to_stream($stream, $dest);
+ fclose($stream);
+ rewind($dest);
+ return $dest;
+ }
+ }
+
+ // Stream the response into the destination stream
+ $dest = is_string($dest)
+ ? new Stream(Utils::open($dest, 'r+'))
+ : Stream::factory($dest);
+
+ Utils::copyToStream($stream, $dest);
+ $dest->seek(0);
+ $stream->close();
+
+ return $dest;
+ }
+
+ /**
+ * Creates an error response for the given stream.
+ *
+ * @param string $url
+ * @param RingException $e
+ *
+ * @return array
+ */
+ private function createErrorResponse($url, RingException $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')
+ ) {
+ $e = new ConnectException($e->getMessage(), 0, $e);
+ }
+
+ return new CompletedFutureArray([
+ 'status' => null,
+ 'body' => null,
+ 'headers' => [],
+ 'effective_url' => $url,
+ 'error' => $e
+ ]);
+ }
+
+ /**
+ * 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 RingException(trim($message));
+ }
+
+ return $resource;
+ }
+
+ private function createStream($url, array $request)
+ {
+ 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 ((!isset($request['version']) || $request['version'] == '1.1')
+ && !Core::hasHeader($request, 'Connection')
+ ) {
+ $request['headers']['Connection'] = ['close'];
+ }
+
+ // Ensure SSL is verified by default
+ if (!isset($request['client']['verify'])) {
+ $request['client']['verify'] = true;
+ }
+
+ $params = [];
+ $options = $this->getDefaultOptions($request);
+
+ if (isset($request['client'])) {
+ foreach ($request['client'] as $key => $value) {
+ $method = "add_{$key}";
+ if (isset($methods[$method])) {
+ $this->{$method}($request, $options, $value, $params);
+ }
+ }
+ }
+
+ return $this->createStreamResource(
+ $url,
+ $request,
+ $options,
+ $this->createContext($request, $options, $params)
+ );
+ }
+
+ private function getDefaultOptions(array $request)
+ {
+ $headers = "";
+ foreach ($request['headers'] as $name => $value) {
+ foreach ((array) $value as $val) {
+ $headers .= "$name: $val\r\n";
+ }
+ }
+
+ $context = [
+ 'http' => [
+ 'method' => $request['http_method'],
+ 'header' => $headers,
+ 'protocol_version' => isset($request['version']) ? $request['version'] : 1.1,
+ 'ignore_errors' => true,
+ 'follow_location' => 0,
+ ],
+ ];
+
+ $body = Core::body($request);
+ if (isset($body)) {
+ $context['http']['content'] = $body;
+ // Prevent the HTTP handler from adding a Content-Type header.
+ if (!Core::hasHeader($request, 'Content-Type')) {
+ $context['http']['header'] .= "Content-Type:\r\n";
+ }
+ }
+
+ $context['http']['header'] = rtrim($context['http']['header']);
+
+ return $context;
+ }
+
+ private function add_proxy(array $request, &$options, $value, &$params)
+ {
+ if (!is_array($value)) {
+ $options['http']['proxy'] = $value;
+ } else {
+ $scheme = isset($request['scheme']) ? $request['scheme'] : 'http';
+ if (isset($value[$scheme])) {
+ $options['http']['proxy'] = $value[$scheme];
+ }
+ }
+ }
+
+ private function add_timeout(array $request, &$options, $value, &$params)
+ {
+ $options['http']['timeout'] = $value;
+ }
+
+ private function add_verify(array $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'] = ClientUtils::getDefaultCaBundle();
+ }
+ } elseif (is_string($value)) {
+ $options['ssl']['cafile'] = $value;
+ if (!file_exists($value)) {
+ throw new RingException("SSL CA bundle not found: $value");
+ }
+ } elseif ($value === false) {
+ $options['ssl']['verify_peer'] = false;
+ $options['ssl']['allow_self_signed'] = true;
+ return;
+ } else {
+ throw new RingException('Invalid verify request option');
+ }
+
+ $options['ssl']['verify_peer'] = true;
+ $options['ssl']['allow_self_signed'] = false;
+ }
+
+ private function add_cert(array $request, &$options, $value, &$params)
+ {
+ if (is_array($value)) {
+ $options['ssl']['passphrase'] = $value[1];
+ $value = $value[0];
+ }
+
+ if (!file_exists($value)) {
+ throw new RingException("SSL certificate not found: {$value}");
+ }
+
+ $options['ssl']['local_cert'] = $value;
+ }
+
+ private function add_progress(array $request, &$options, $value, &$params)
+ {
+ $fn = function ($code, $_1, $_2, $_3, $transferred, $total) use ($value) {
+ if ($code == STREAM_NOTIFY_PROGRESS) {
+ $value($total, $transferred, null, null);
+ }
+ };
+
+ // Wrap the existing function if needed.
+ $params['notification'] = isset($params['notification'])
+ ? Core::callArray([$params['notification'], $fn])
+ : $fn;
+ }
+
+ private function add_debug(array $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 = Core::getDebugResource($value);
+ $ident = $request['http_method'] . ' ' . Core::url($request);
+ $fn = 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");
+ };
+
+ // Wrap the existing function if needed.
+ $params['notification'] = isset($params['notification'])
+ ? Core::callArray([$params['notification'], $fn])
+ : $fn;
+ }
+
+ private function applyCustomOptions(array $request, array &$options)
+ {
+ if (!isset($request['client']['stream_context'])) {
+ return;
+ }
+
+ if (!is_array($request['client']['stream_context'])) {
+ throw new RingException('stream_context must be an array');
+ }
+
+ $options = array_replace_recursive(
+ $options,
+ $request['client']['stream_context']
+ );
+ }
+
+ private function createContext(array $request, array $options, array $params)
+ {
+ $this->applyCustomOptions($request, $options);
+ return $this->createResource(
+ function () use ($request, $options, $params) {
+ return stream_context_create($options, $params);
+ },
+ $request,
+ $options
+ );
+ }
+
+ private function createStreamResource(
+ $url,
+ array $request,
+ array $options,
+ $context
+ ) {
+ return $this->createResource(
+ function () use ($url, $context) {
+ if (false === strpos($url, 'http')) {
+ trigger_error("URL is invalid: {$url}", E_USER_WARNING);
+ return null;
+ }
+ $resource = fopen($url, 'r', null, $context);
+ $this->lastHeaders = $http_response_header;
+ return $resource;
+ },
+ $request,
+ $options
+ );
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Core.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Core.php
new file mode 100644
index 00000000..dd7d1a0c
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Core.php
@@ -0,0 +1,364 @@
+<?php
+namespace GuzzleHttp\Ring;
+
+use GuzzleHttp\Stream\StreamInterface;
+use GuzzleHttp\Ring\Future\FutureArrayInterface;
+use GuzzleHttp\Ring\Future\FutureArray;
+
+/**
+ * Provides core functionality of Ring handlers and middleware.
+ */
+class Core
+{
+ /**
+ * Returns a function that calls all of the provided functions, in order,
+ * passing the arguments provided to the composed function to each function.
+ *
+ * @param callable[] $functions Array of functions to proxy to.
+ *
+ * @return callable
+ */
+ public static function callArray(array $functions)
+ {
+ return function () use ($functions) {
+ $args = func_get_args();
+ foreach ($functions as $fn) {
+ call_user_func_array($fn, $args);
+ }
+ };
+ }
+
+ /**
+ * Gets an array of header line values from a message for a specific header
+ *
+ * This method searches through the "headers" key of a message for a header
+ * using a case-insensitive search.
+ *
+ * @param array $message Request or response hash.
+ * @param string $header Header to retrieve
+ *
+ * @return array
+ */
+ public static function headerLines($message, $header)
+ {
+ $result = [];
+
+ if (!empty($message['headers'])) {
+ foreach ($message['headers'] as $name => $value) {
+ if (!strcasecmp($name, $header)) {
+ $result = array_merge($result, $value);
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Gets a header value from a message as a string or null
+ *
+ * This method searches through the "headers" key of a message for a header
+ * using a case-insensitive search. The lines of the header are imploded
+ * using commas into a single string return value.
+ *
+ * @param array $message Request or response hash.
+ * @param string $header Header to retrieve
+ *
+ * @return string|null Returns the header string if found, or null if not.
+ */
+ public static function header($message, $header)
+ {
+ $match = self::headerLines($message, $header);
+ return $match ? implode(', ', $match) : null;
+ }
+
+ /**
+ * Returns the first header value from a message as a string or null. If
+ * a header line contains multiple values separated by a comma, then this
+ * function will return the first value in the list.
+ *
+ * @param array $message Request or response hash.
+ * @param string $header Header to retrieve
+ *
+ * @return string|null Returns the value as a string if found.
+ */
+ public static function firstHeader($message, $header)
+ {
+ if (!empty($message['headers'])) {
+ foreach ($message['headers'] as $name => $value) {
+ if (!strcasecmp($name, $header)) {
+ // Return the match itself if it is a single value.
+ $pos = strpos($value[0], ',');
+ return $pos ? substr($value[0], 0, $pos) : $value[0];
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns true if a message has the provided case-insensitive header.
+ *
+ * @param array $message Request or response hash.
+ * @param string $header Header to check
+ *
+ * @return bool
+ */
+ public static function hasHeader($message, $header)
+ {
+ if (!empty($message['headers'])) {
+ foreach ($message['headers'] as $name => $value) {
+ if (!strcasecmp($name, $header)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * 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
+ */
+ public static function headersFromLines($lines)
+ {
+ $headers = [];
+
+ foreach ($lines as $line) {
+ $parts = explode(':', $line, 2);
+ $headers[trim($parts[0])][] = isset($parts[1])
+ ? trim($parts[1])
+ : null;
+ }
+
+ return $headers;
+ }
+
+ /**
+ * Removes a header from a message using a case-insensitive comparison.
+ *
+ * @param array $message Message that contains 'headers'
+ * @param string $header Header to remove
+ *
+ * @return array
+ */
+ public static function removeHeader(array $message, $header)
+ {
+ if (isset($message['headers'])) {
+ foreach (array_keys($message['headers']) as $key) {
+ if (!strcasecmp($header, $key)) {
+ unset($message['headers'][$key]);
+ }
+ }
+ }
+
+ return $message;
+ }
+
+ /**
+ * Replaces any existing case insensitive headers with the given value.
+ *
+ * @param array $message Message that contains 'headers'
+ * @param string $header Header to set.
+ * @param array $value Value to set.
+ *
+ * @return array
+ */
+ public static function setHeader(array $message, $header, array $value)
+ {
+ $message = self::removeHeader($message, $header);
+ $message['headers'][$header] = $value;
+
+ return $message;
+ }
+
+ /**
+ * Creates a URL string from a request.
+ *
+ * If the "url" key is present on the request, it is returned, otherwise
+ * the url is built up based on the scheme, host, uri, and query_string
+ * request values.
+ *
+ * @param array $request Request to get the URL from
+ *
+ * @return string Returns the request URL as a string.
+ * @throws \InvalidArgumentException if no Host header is present.
+ */
+ public static function url(array $request)
+ {
+ if (isset($request['url'])) {
+ return $request['url'];
+ }
+
+ $uri = (isset($request['scheme'])
+ ? $request['scheme'] : 'http') . '://';
+
+ if ($host = self::header($request, 'host')) {
+ $uri .= $host;
+ } else {
+ throw new \InvalidArgumentException('No Host header was provided');
+ }
+
+ if (isset($request['uri'])) {
+ $uri .= $request['uri'];
+ }
+
+ if (isset($request['query_string'])) {
+ $uri .= '?' . $request['query_string'];
+ }
+
+ return $uri;
+ }
+
+ /**
+ * Reads the body of a message into a string.
+ *
+ * @param array|FutureArrayInterface $message Array containing a "body" key
+ *
+ * @return null|string Returns the body as a string or null if not set.
+ * @throws \InvalidArgumentException if a request body is invalid.
+ */
+ public static function body($message)
+ {
+ if (!isset($message['body'])) {
+ return null;
+ }
+
+ if ($message['body'] instanceof StreamInterface) {
+ return (string) $message['body'];
+ }
+
+ switch (gettype($message['body'])) {
+ case 'string':
+ return $message['body'];
+ case 'resource':
+ return stream_get_contents($message['body']);
+ case 'object':
+ if ($message['body'] instanceof \Iterator) {
+ return implode('', iterator_to_array($message['body']));
+ } elseif (method_exists($message['body'], '__toString')) {
+ return (string) $message['body'];
+ }
+ default:
+ throw new \InvalidArgumentException('Invalid request body: '
+ . self::describeType($message['body']));
+ }
+ }
+
+ /**
+ * Rewind the body of the provided message if possible.
+ *
+ * @param array $message Message that contains a 'body' field.
+ *
+ * @return bool Returns true on success, false on failure
+ */
+ public static function rewindBody($message)
+ {
+ if ($message['body'] instanceof StreamInterface) {
+ return $message['body']->seek(0);
+ }
+
+ if ($message['body'] instanceof \Generator) {
+ return false;
+ }
+
+ if ($message['body'] instanceof \Iterator) {
+ $message['body']->rewind();
+ return true;
+ }
+
+ if (is_resource($message['body'])) {
+ return rewind($message['body']);
+ }
+
+ return is_string($message['body'])
+ || (is_object($message['body'])
+ && method_exists($message['body'], '__toString'));
+ }
+
+ /**
+ * 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.
+ */
+ public static function describeType($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()));
+ }
+ }
+
+ /**
+ * Sleep for the specified amount of time specified in the request's
+ * ['client']['delay'] option if present.
+ *
+ * This function should only be used when a non-blocking sleep is not
+ * possible.
+ *
+ * @param array $request Request to sleep
+ */
+ public static function doSleep(array $request)
+ {
+ if (isset($request['client']['delay'])) {
+ usleep($request['client']['delay'] * 1000);
+ }
+ }
+
+ /**
+ * Returns a proxied future that modifies the dereferenced value of another
+ * future using a promise.
+ *
+ * @param FutureArrayInterface $future Future to wrap with a new future
+ * @param callable $onFulfilled Invoked when the future fulfilled
+ * @param callable $onRejected Invoked when the future rejected
+ * @param callable $onProgress Invoked when the future progresses
+ *
+ * @return FutureArray
+ */
+ public static function proxy(
+ FutureArrayInterface $future,
+ callable $onFulfilled = null,
+ callable $onRejected = null,
+ callable $onProgress = null
+ ) {
+ return new FutureArray(
+ $future->then($onFulfilled, $onRejected, $onProgress),
+ [$future, 'wait'],
+ [$future, 'cancel']
+ );
+ }
+
+ /**
+ * Returns a debug stream based on the provided variable.
+ *
+ * @param mixed $value Optional value
+ *
+ * @return resource
+ */
+ public static function getDebugResource($value = null)
+ {
+ if (is_resource($value)) {
+ return $value;
+ } elseif (defined('STDOUT')) {
+ return STDOUT;
+ } else {
+ return fopen('php://output', 'w');
+ }
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Exception/CancelledException.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Exception/CancelledException.php
new file mode 100644
index 00000000..95b353ac
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Exception/CancelledException.php
@@ -0,0 +1,7 @@
+<?php
+namespace GuzzleHttp\Ring\Exception;
+
+/**
+ * Marker interface for cancelled exceptions.
+ */
+interface CancelledException {}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Exception/CancelledFutureAccessException.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Exception/CancelledFutureAccessException.php
new file mode 100644
index 00000000..4a14574d
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Exception/CancelledFutureAccessException.php
@@ -0,0 +1,4 @@
+<?php
+namespace GuzzleHttp\Ring\Exception;
+
+class CancelledFutureAccessException extends RingException implements CancelledException {}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Exception/ConnectException.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Exception/ConnectException.php
new file mode 100644
index 00000000..925cd133
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Exception/ConnectException.php
@@ -0,0 +1,7 @@
+<?php
+namespace GuzzleHttp\Ring\Exception;
+
+/**
+ * Occurs when the connection failed.
+ */
+class ConnectException extends RingException {}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Exception/RingException.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Exception/RingException.php
new file mode 100644
index 00000000..eed0daf7
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Exception/RingException.php
@@ -0,0 +1,4 @@
+<?php
+namespace GuzzleHttp\Ring\Exception;
+
+class RingException extends \RuntimeException {};
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Future/BaseFutureTrait.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Future/BaseFutureTrait.php
new file mode 100644
index 00000000..e6a7ca77
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Future/BaseFutureTrait.php
@@ -0,0 +1,125 @@
+<?php
+namespace GuzzleHttp\Ring\Future;
+
+use GuzzleHttp\Ring\Exception\CancelledFutureAccessException;
+use GuzzleHttp\Ring\Exception\RingException;
+use React\Promise\PromiseInterface;
+
+/**
+ * Implements common future functionality built on top of promises.
+ */
+trait BaseFutureTrait
+{
+ /** @var callable */
+ private $waitfn;
+
+ /** @var callable */
+ private $cancelfn;
+
+ /** @var PromiseInterface */
+ private $wrappedPromise;
+
+ /** @var \Exception Error encountered. */
+ private $error;
+
+ /** @var mixed Result of the future */
+ private $result;
+
+ private $isRealized = false;
+
+ /**
+ * @param PromiseInterface $promise Promise to shadow with the future.
+ * @param callable $wait Function that blocks until the deferred
+ * computation has been resolved. This
+ * function MUST resolve the deferred value
+ * associated with the supplied promise.
+ * @param callable $cancel If possible and reasonable, provide a
+ * function that can be used to cancel the
+ * future from completing.
+ */
+ public function __construct(
+ PromiseInterface $promise,
+ callable $wait = null,
+ callable $cancel = null
+ ) {
+ $this->wrappedPromise = $promise;
+ $this->waitfn = $wait;
+ $this->cancelfn = $cancel;
+ }
+
+ public function wait()
+ {
+ if (!$this->isRealized) {
+ $this->addShadow();
+ if (!$this->isRealized && $this->waitfn) {
+ $this->invokeWait();
+ }
+ if (!$this->isRealized) {
+ $this->error = new RingException('Waiting did not resolve future');
+ }
+ }
+
+ if ($this->error) {
+ throw $this->error;
+ }
+
+ return $this->result;
+ }
+
+ public function promise()
+ {
+ return $this->wrappedPromise;
+ }
+
+ public function then(
+ callable $onFulfilled = null,
+ callable $onRejected = null,
+ callable $onProgress = null
+ ) {
+ return $this->wrappedPromise->then($onFulfilled, $onRejected, $onProgress);
+ }
+
+ public function cancel()
+ {
+ if (!$this->isRealized) {
+ $cancelfn = $this->cancelfn;
+ $this->waitfn = $this->cancelfn = null;
+ $this->isRealized = true;
+ $this->error = new CancelledFutureAccessException();
+ if ($cancelfn) {
+ $cancelfn($this);
+ }
+ }
+ }
+
+ private function addShadow()
+ {
+ // Get the result and error when the promise is resolved. Note that
+ // calling this function might trigger the resolution immediately.
+ $this->wrappedPromise->then(
+ function ($value) {
+ $this->isRealized = true;
+ $this->result = $value;
+ $this->waitfn = $this->cancelfn = null;
+ },
+ function ($error) {
+ $this->isRealized = true;
+ $this->error = $error;
+ $this->waitfn = $this->cancelfn = null;
+ }
+ );
+ }
+
+ private function invokeWait()
+ {
+ try {
+ $wait = $this->waitfn;
+ $this->waitfn = null;
+ $wait();
+ } catch (\Exception $e) {
+ // Defer can throw to reject.
+ $this->error = $e;
+ $this->isRealized = true;
+ }
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureArray.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureArray.php
new file mode 100644
index 00000000..0a90c939
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureArray.php
@@ -0,0 +1,43 @@
+<?php
+namespace GuzzleHttp\Ring\Future;
+
+/**
+ * Represents a future array that has been completed successfully.
+ */
+class CompletedFutureArray extends CompletedFutureValue implements FutureArrayInterface
+{
+ public function __construct(array $result)
+ {
+ parent::__construct($result);
+ }
+
+ public function offsetExists($offset)
+ {
+ return isset($this->result[$offset]);
+ }
+
+ public function offsetGet($offset)
+ {
+ return $this->result[$offset];
+ }
+
+ public function offsetSet($offset, $value)
+ {
+ $this->result[$offset] = $value;
+ }
+
+ public function offsetUnset($offset)
+ {
+ unset($this->result[$offset]);
+ }
+
+ public function count()
+ {
+ return count($this->result);
+ }
+
+ public function getIterator()
+ {
+ return new \ArrayIterator($this->result);
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureValue.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureValue.php
new file mode 100644
index 00000000..0d25af72
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Future/CompletedFutureValue.php
@@ -0,0 +1,57 @@
+<?php
+namespace GuzzleHttp\Ring\Future;
+
+use React\Promise\FulfilledPromise;
+use React\Promise\RejectedPromise;
+
+/**
+ * Represents a future value that has been resolved or rejected.
+ */
+class CompletedFutureValue implements FutureInterface
+{
+ protected $result;
+ protected $error;
+
+ private $cachedPromise;
+
+ /**
+ * @param mixed $result Resolved result
+ * @param \Exception $e Error. Pass a GuzzleHttp\Ring\Exception\CancelledFutureAccessException
+ * to mark the future as cancelled.
+ */
+ public function __construct($result, \Exception $e = null)
+ {
+ $this->result = $result;
+ $this->error = $e;
+ }
+
+ public function wait()
+ {
+ if ($this->error) {
+ throw $this->error;
+ }
+
+ return $this->result;
+ }
+
+ public function cancel() {}
+
+ public function promise()
+ {
+ if (!$this->cachedPromise) {
+ $this->cachedPromise = $this->error
+ ? new RejectedPromise($this->error)
+ : new FulfilledPromise($this->result);
+ }
+
+ return $this->cachedPromise;
+ }
+
+ public function then(
+ callable $onFulfilled = null,
+ callable $onRejected = null,
+ callable $onProgress = null
+ ) {
+ return $this->promise()->then($onFulfilled, $onRejected, $onProgress);
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Future/FutureArray.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Future/FutureArray.php
new file mode 100644
index 00000000..3d64c964
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Future/FutureArray.php
@@ -0,0 +1,40 @@
+<?php
+namespace GuzzleHttp\Ring\Future;
+
+/**
+ * Represents a future array value that when dereferenced returns an array.
+ */
+class FutureArray implements FutureArrayInterface
+{
+ use MagicFutureTrait;
+
+ public function offsetExists($offset)
+ {
+ return isset($this->_value[$offset]);
+ }
+
+ public function offsetGet($offset)
+ {
+ return $this->_value[$offset];
+ }
+
+ public function offsetSet($offset, $value)
+ {
+ $this->_value[$offset] = $value;
+ }
+
+ public function offsetUnset($offset)
+ {
+ unset($this->_value[$offset]);
+ }
+
+ public function count()
+ {
+ return count($this->_value);
+ }
+
+ public function getIterator()
+ {
+ return new \ArrayIterator($this->_value);
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Future/FutureArrayInterface.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Future/FutureArrayInterface.php
new file mode 100644
index 00000000..58f5f736
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Future/FutureArrayInterface.php
@@ -0,0 +1,11 @@
+<?php
+namespace GuzzleHttp\Ring\Future;
+
+/**
+ * Future that provides array-like access.
+ */
+interface FutureArrayInterface extends
+ FutureInterface,
+ \ArrayAccess,
+ \Countable,
+ \IteratorAggregate {};
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Future/FutureInterface.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Future/FutureInterface.php
new file mode 100644
index 00000000..43d18117
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Future/FutureInterface.php
@@ -0,0 +1,40 @@
+<?php
+namespace GuzzleHttp\Ring\Future;
+
+use React\Promise\PromiseInterface;
+use React\Promise\PromisorInterface;
+
+/**
+ * Represents the result of a computation that may not have completed yet.
+ *
+ * You can use the future in a blocking manner using the wait() function, or
+ * you can use a promise from the future to receive the result when the future
+ * has been resolved.
+ *
+ * When the future is dereferenced using wait(), the result of the computation
+ * is cached and returned for subsequent calls to wait(). If the result of the
+ * computation has not yet completed when wait() is called, the call to wait()
+ * will block until the future has completed.
+ */
+interface FutureInterface extends PromiseInterface, PromisorInterface
+{
+ /**
+ * Returns the result of the future either from cache or by blocking until
+ * it is complete.
+ *
+ * This method must block until the future has a result or is cancelled.
+ * Throwing an exception in the wait() method will mark the future as
+ * realized and will throw the exception each time wait() is called.
+ * Throwing an instance of GuzzleHttp\Ring\CancelledException will mark
+ * the future as realized, will not throw immediately, but will throw the
+ * exception if the future's wait() method is called again.
+ *
+ * @return mixed
+ */
+ public function wait();
+
+ /**
+ * Cancels the future, if possible.
+ */
+ public function cancel();
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Future/FutureValue.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Future/FutureValue.php
new file mode 100644
index 00000000..4cac9281
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Future/FutureValue.php
@@ -0,0 +1,12 @@
+<?php
+namespace GuzzleHttp\Ring\Future;
+
+/**
+ * Represents a future value that responds to wait() to retrieve the promised
+ * value, but can also return promises that are delivered the value when it is
+ * available.
+ */
+class FutureValue implements FutureInterface
+{
+ use BaseFutureTrait;
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/src/Future/MagicFutureTrait.php b/www/wiki/vendor/guzzlehttp/ringphp/src/Future/MagicFutureTrait.php
new file mode 100644
index 00000000..58d779db
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/src/Future/MagicFutureTrait.php
@@ -0,0 +1,32 @@
+<?php
+namespace GuzzleHttp\Ring\Future;
+
+/**
+ * Implements common future functionality that is triggered when the result
+ * property is accessed via a magic __get method.
+ *
+ * @property mixed $_value Actual data used by the future. Accessing this
+ * property will cause the future to block if needed.
+ */
+trait MagicFutureTrait
+{
+ use BaseFutureTrait;
+
+ /**
+ * This function handles retrieving the dereferenced result when requested.
+ *
+ * @param string $name Should always be "data" or an exception is thrown.
+ *
+ * @return mixed Returns the dereferenced data.
+ * @throws \RuntimeException
+ * @throws \GuzzleHttp\Ring\Exception\CancelledException
+ */
+ public function __get($name)
+ {
+ if ($name !== '_value') {
+ throw new \RuntimeException("Class has no {$name} property");
+ }
+
+ return $this->_value = $this->wait();
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/CurlFactoryTest.php b/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/CurlFactoryTest.php
new file mode 100644
index 00000000..ebde187c
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/CurlFactoryTest.php
@@ -0,0 +1,821 @@
+<?php
+// Override curl_setopt_array() to get the last set curl options
+namespace GuzzleHttp\Ring\Client {
+ function curl_setopt_array($handle, array $options) {
+ if (!empty($_SERVER['curl_test'])) {
+ $_SERVER['_curl'] = $options;
+ } else {
+ unset($_SERVER['_curl']);
+ }
+ \curl_setopt_array($handle, $options);
+ }
+}
+
+namespace GuzzleHttp\Tests\Ring\Client {
+
+use GuzzleHttp\Ring\Client\CurlFactory;
+use GuzzleHttp\Ring\Client\CurlMultiHandler;
+use GuzzleHttp\Ring\Client\MockHandler;
+use GuzzleHttp\Ring\Core;
+use GuzzleHttp\Stream\FnStream;
+use GuzzleHttp\Stream\NoSeekStream;
+use GuzzleHttp\Stream\Stream;
+
+class CurlFactoryTest extends \PHPUnit_Framework_TestCase
+{
+ public static function setUpBeforeClass()
+ {
+ $_SERVER['curl_test'] = true;
+ unset($_SERVER['_curl']);
+ }
+
+ public static function tearDownAfterClass()
+ {
+ unset($_SERVER['_curl'], $_SERVER['curl_test']);
+ }
+
+ public function testCreatesCurlHandle()
+ {
+ Server::flush();
+ Server::enqueue([[
+ 'status' => 200,
+ 'headers' => [
+ 'Foo' => ['Bar'],
+ 'Baz' => ['bam'],
+ 'Content-Length' => [2],
+ ],
+ 'body' => 'hi',
+ ]]);
+
+ $stream = Stream::factory();
+
+ $request = [
+ 'http_method' => 'PUT',
+ 'headers' => [
+ 'host' => [Server::$url],
+ 'Hi' => [' 123'],
+ ],
+ 'body' => 'testing',
+ 'client' => ['save_to' => $stream],
+ ];
+
+ $f = new CurlFactory();
+ $result = $f($request);
+ $this->assertInternalType('array', $result);
+ $this->assertCount(3, $result);
+ $this->assertInternalType('resource', $result[0]);
+ $this->assertInternalType('array', $result[1]);
+ $this->assertSame($stream, $result[2]);
+ curl_close($result[0]);
+
+ $this->assertEquals('PUT', $_SERVER['_curl'][CURLOPT_CUSTOMREQUEST]);
+ $this->assertEquals(
+ 'http://http://127.0.0.1:8125/',
+ $_SERVER['_curl'][CURLOPT_URL]
+ );
+ // Sends via post fields when the request is small enough
+ $this->assertEquals('testing', $_SERVER['_curl'][CURLOPT_POSTFIELDS]);
+ $this->assertEquals(0, $_SERVER['_curl'][CURLOPT_RETURNTRANSFER]);
+ $this->assertEquals(0, $_SERVER['_curl'][CURLOPT_HEADER]);
+ $this->assertEquals(150, $_SERVER['_curl'][CURLOPT_CONNECTTIMEOUT]);
+ $this->assertInstanceOf('Closure', $_SERVER['_curl'][CURLOPT_HEADERFUNCTION]);
+
+ if (defined('CURLOPT_PROTOCOLS')) {
+ $this->assertEquals(
+ CURLPROTO_HTTP | CURLPROTO_HTTPS,
+ $_SERVER['_curl'][CURLOPT_PROTOCOLS]
+ );
+ }
+
+ $this->assertContains('Expect:', $_SERVER['_curl'][CURLOPT_HTTPHEADER]);
+ $this->assertContains('Accept:', $_SERVER['_curl'][CURLOPT_HTTPHEADER]);
+ $this->assertContains('Content-Type:', $_SERVER['_curl'][CURLOPT_HTTPHEADER]);
+ $this->assertContains('Hi: 123', $_SERVER['_curl'][CURLOPT_HTTPHEADER]);
+ $this->assertContains('host: http://127.0.0.1:8125/', $_SERVER['_curl'][CURLOPT_HTTPHEADER]);
+ }
+
+ public function testSendsHeadRequests()
+ {
+ Server::flush();
+ Server::enqueue([['status' => 200]]);
+ $a = new CurlMultiHandler();
+ $response = $a([
+ 'http_method' => 'HEAD',
+ 'headers' => ['host' => [Server::$host]],
+ ]);
+ $response->wait();
+ $this->assertEquals(true, $_SERVER['_curl'][CURLOPT_NOBODY]);
+ $checks = [CURLOPT_WRITEFUNCTION, CURLOPT_READFUNCTION, CURLOPT_FILE, CURLOPT_INFILE];
+ foreach ($checks as $check) {
+ $this->assertArrayNotHasKey($check, $_SERVER['_curl']);
+ }
+ $this->assertEquals('HEAD', Server::received()[0]['http_method']);
+ }
+
+ public function testCanAddCustomCurlOptions()
+ {
+ Server::flush();
+ Server::enqueue([['status' => 200]]);
+ $a = new CurlMultiHandler();
+ $a([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['curl' => [CURLOPT_LOW_SPEED_LIMIT => 10]],
+ ]);
+ $this->assertEquals(10, $_SERVER['_curl'][CURLOPT_LOW_SPEED_LIMIT]);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage SSL CA bundle not found: /does/not/exist
+ */
+ public function testValidatesVerify()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['verify' => '/does/not/exist'],
+ ]);
+ }
+
+ public function testCanSetVerifyToFile()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['verify' => __FILE__],
+ ]);
+ $this->assertEquals(__FILE__, $_SERVER['_curl'][CURLOPT_CAINFO]);
+ $this->assertEquals(2, $_SERVER['_curl'][CURLOPT_SSL_VERIFYHOST]);
+ $this->assertEquals(true, $_SERVER['_curl'][CURLOPT_SSL_VERIFYPEER]);
+ }
+
+ public function testAddsVerifyAsTrue()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['verify' => true],
+ ]);
+ $this->assertEquals(2, $_SERVER['_curl'][CURLOPT_SSL_VERIFYHOST]);
+ $this->assertEquals(true, $_SERVER['_curl'][CURLOPT_SSL_VERIFYPEER]);
+ $this->assertArrayNotHasKey(CURLOPT_CAINFO, $_SERVER['_curl']);
+ }
+
+ public function testCanDisableVerify()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['verify' => false],
+ ]);
+ $this->assertEquals(0, $_SERVER['_curl'][CURLOPT_SSL_VERIFYHOST]);
+ $this->assertEquals(false, $_SERVER['_curl'][CURLOPT_SSL_VERIFYPEER]);
+ }
+
+ public function testAddsProxy()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['proxy' => 'http://bar.com'],
+ ]);
+ $this->assertEquals('http://bar.com', $_SERVER['_curl'][CURLOPT_PROXY]);
+ }
+
+ public function testAddsViaScheme()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'scheme' => 'http',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => [
+ 'proxy' => ['http' => 'http://bar.com', 'https' => 'https://t'],
+ ],
+ ]);
+ $this->assertEquals('http://bar.com', $_SERVER['_curl'][CURLOPT_PROXY]);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage SSL private key not found: /does/not/exist
+ */
+ public function testValidatesSslKey()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['ssl_key' => '/does/not/exist'],
+ ]);
+ }
+
+ public function testAddsSslKey()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['ssl_key' => __FILE__],
+ ]);
+ $this->assertEquals(__FILE__, $_SERVER['_curl'][CURLOPT_SSLKEY]);
+ }
+
+ public function testAddsSslKeyWithPassword()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['ssl_key' => [__FILE__, 'test']],
+ ]);
+ $this->assertEquals(__FILE__, $_SERVER['_curl'][CURLOPT_SSLKEY]);
+ $this->assertEquals('test', $_SERVER['_curl'][CURLOPT_SSLKEYPASSWD]);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage SSL certificate not found: /does/not/exist
+ */
+ public function testValidatesCert()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['cert' => '/does/not/exist'],
+ ]);
+ }
+
+ public function testAddsCert()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['cert' => __FILE__],
+ ]);
+ $this->assertEquals(__FILE__, $_SERVER['_curl'][CURLOPT_SSLCERT]);
+ }
+
+ public function testAddsCertWithPassword()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['cert' => [__FILE__, 'test']],
+ ]);
+ $this->assertEquals(__FILE__, $_SERVER['_curl'][CURLOPT_SSLCERT]);
+ $this->assertEquals('test', $_SERVER['_curl'][CURLOPT_SSLCERTPASSWD]);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage progress client option must be callable
+ */
+ public function testValidatesProgress()
+ {
+ $f = new CurlFactory();
+ $f([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['foo.com']],
+ 'client' => ['progress' => 'foo'],
+ ]);
+ }
+
+ public function testEmitsDebugInfoToStream()
+ {
+ $res = fopen('php://memory', 'r+');
+ Server::flush();
+ Server::enqueue([['status' => 200]]);
+ $a = new CurlMultiHandler();
+ $response = $a([
+ 'http_method' => 'HEAD',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['debug' => $res],
+ ]);
+ $response->wait();
+ rewind($res);
+ $output = str_replace("\r", '', stream_get_contents($res));
+ $this->assertContains(
+ "> HEAD / HTTP/1.1\nhost: 127.0.0.1:8125\n\n",
+ $output
+ );
+ $this->assertContains("< HTTP/1.1 200", $output);
+ fclose($res);
+ }
+
+ public function testEmitsProgressToFunction()
+ {
+ Server::flush();
+ Server::enqueue([['status' => 200]]);
+ $a = new CurlMultiHandler();
+ $called = [];
+ $response = $a([
+ 'http_method' => 'HEAD',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => [
+ 'progress' => function () use (&$called) {
+ $called[] = func_get_args();
+ },
+ ],
+ ]);
+ $response->wait();
+ $this->assertNotEmpty($called);
+ foreach ($called as $call) {
+ $this->assertCount(4, $call);
+ }
+ }
+
+ private function addDecodeResponse($withEncoding = true)
+ {
+ $content = gzencode('test');
+ $response = [
+ 'status' => 200,
+ 'reason' => 'OK',
+ 'headers' => ['Content-Length' => [strlen($content)]],
+ 'body' => $content,
+ ];
+
+ if ($withEncoding) {
+ $response['headers']['Content-Encoding'] = ['gzip'];
+ }
+
+ Server::flush();
+ Server::enqueue([$response]);
+
+ return $content;
+ }
+
+ public function testDecodesGzippedResponses()
+ {
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['decode_content' => true],
+ ]);
+ $response->wait();
+ $this->assertEquals('test', Core::body($response));
+ $this->assertEquals('', $_SERVER['_curl'][CURLOPT_ENCODING]);
+ $sent = Server::received()[0];
+ $this->assertNull(Core::header($sent, 'Accept-Encoding'));
+ }
+
+ public function testDecodesGzippedResponsesWithHeader()
+ {
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => [
+ 'host' => [Server::$host],
+ 'Accept-Encoding' => ['gzip'],
+ ],
+ 'client' => ['decode_content' => true],
+ ]);
+ $response->wait();
+ $this->assertEquals('gzip', $_SERVER['_curl'][CURLOPT_ENCODING]);
+ $sent = Server::received()[0];
+ $this->assertEquals('gzip', Core::header($sent, 'Accept-Encoding'));
+ $this->assertEquals('test', Core::body($response));
+ }
+
+ public function testDoesNotForceDecode()
+ {
+ $content = $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['decode_content' => false],
+ ]);
+ $response->wait();
+ $sent = Server::received()[0];
+ $this->assertNull(Core::header($sent, 'Accept-Encoding'));
+ $this->assertEquals($content, Core::body($response));
+ }
+
+ public function testProtocolVersion()
+ {
+ Server::flush();
+ Server::enqueue([['status' => 200]]);
+ $a = new CurlMultiHandler();
+ $a([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'version' => 1.0,
+ ]);
+ $this->assertEquals(CURL_HTTP_VERSION_1_0, $_SERVER['_curl'][CURLOPT_HTTP_VERSION]);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testValidatesSaveTo()
+ {
+ $handler = new CurlMultiHandler();
+ $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['save_to' => true],
+ ]);
+ }
+
+ public function testSavesToStream()
+ {
+ $stream = fopen('php://memory', 'r+');
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => [
+ 'decode_content' => true,
+ 'save_to' => $stream,
+ ],
+ ]);
+ $response->wait();
+ rewind($stream);
+ $this->assertEquals('test', stream_get_contents($stream));
+ }
+
+ public function testSavesToGuzzleStream()
+ {
+ $stream = Stream::factory();
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => [
+ 'decode_content' => true,
+ 'save_to' => $stream,
+ ],
+ ]);
+ $response->wait();
+ $this->assertEquals('test', (string) $stream);
+ }
+
+ public function testSavesToFileOnDisk()
+ {
+ $tmpfile = tempnam(sys_get_temp_dir(), 'testfile');
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => [
+ 'decode_content' => true,
+ 'save_to' => $tmpfile,
+ ],
+ ]);
+ $response->wait();
+ $this->assertEquals('test', file_get_contents($tmpfile));
+ unlink($tmpfile);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testValidatesBody()
+ {
+ $handler = new CurlMultiHandler();
+ $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'body' => false,
+ ]);
+ }
+
+ public function testAddsLargePayloadFromStreamWithNoSizeUsingChunked()
+ {
+ $stream = Stream::factory('foo');
+ $stream = FnStream::decorate($stream, [
+ 'getSize' => function () {
+ return null;
+ }
+ ]);
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'body' => $stream,
+ ]);
+ $response->wait();
+ $sent = Server::received()[0];
+ $this->assertEquals('chunked', Core::header($sent, 'Transfer-Encoding'));
+ $this->assertNull(Core::header($sent, 'Content-Length'));
+ $this->assertEquals('foo', $sent['body']);
+ }
+
+ public function testAddsPayloadFromIterator()
+ {
+ $iter = new \ArrayIterator(['f', 'o', 'o']);
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'body' => $iter,
+ ]);
+ $response->wait();
+ $sent = Server::received()[0];
+ $this->assertEquals('chunked', Core::header($sent, 'Transfer-Encoding'));
+ $this->assertNull(Core::header($sent, 'Content-Length'));
+ $this->assertEquals('foo', $sent['body']);
+ }
+
+ public function testAddsPayloadFromResource()
+ {
+ $res = fopen('php://memory', 'r+');
+ $data = str_repeat('.', 1000000);
+ fwrite($res, $data);
+ rewind($res);
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => [
+ 'host' => [Server::$host],
+ 'content-length' => [1000000],
+ ],
+ 'body' => $res,
+ ]);
+ $response->wait();
+ $sent = Server::received()[0];
+ $this->assertNull(Core::header($sent, 'Transfer-Encoding'));
+ $this->assertEquals(1000000, Core::header($sent, 'Content-Length'));
+ $this->assertEquals($data, $sent['body']);
+ }
+
+ public function testAddsContentLengthFromStream()
+ {
+ $stream = Stream::factory('foo');
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'body' => $stream,
+ ]);
+ $response->wait();
+ $sent = Server::received()[0];
+ $this->assertEquals(3, Core::header($sent, 'Content-Length'));
+ $this->assertNull(Core::header($sent, 'Transfer-Encoding'));
+ $this->assertEquals('foo', $sent['body']);
+ }
+
+ public function testDoesNotAddMultipleContentLengthHeaders()
+ {
+ $this->addDecodeResponse();
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => [
+ 'host' => [Server::$host],
+ 'content-length' => [3],
+ ],
+ 'body' => 'foo',
+ ]);
+ $response->wait();
+ $sent = Server::received()[0];
+ $this->assertEquals(3, Core::header($sent, 'Content-Length'));
+ $this->assertNull(Core::header($sent, 'Transfer-Encoding'));
+ $this->assertEquals('foo', $sent['body']);
+ }
+
+ public function testSendsPostWithNoBodyOrDefaultContentType()
+ {
+ Server::flush();
+ Server::enqueue([['status' => 200]]);
+ $handler = new CurlMultiHandler();
+ $response = $handler([
+ 'http_method' => 'POST',
+ 'uri' => '/',
+ 'headers' => ['host' => [Server::$host]],
+ ]);
+ $response->wait();
+ $received = Server::received()[0];
+ $this->assertEquals('POST', $received['http_method']);
+ $this->assertNull(Core::header($received, 'content-type'));
+ $this->assertSame('0', Core::firstHeader($received, 'content-length'));
+ }
+
+ public function testParseProtocolVersion()
+ {
+ $res = CurlFactory::createResponse(
+ function () {},
+ [],
+ ['curl' => ['errno' => null]],
+ ['HTTP/1.1 200 Ok'],
+ null
+ );
+
+ $this->assertSame('1.1', $res['version']);
+ }
+
+ public function testFailsWhenNoResponseAndNoBody()
+ {
+ $res = CurlFactory::createResponse(function () {}, [], [], [], null);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Exception\RingException', $res['error']);
+ $this->assertContains(
+ 'No response was received for a request with no body',
+ $res['error']->getMessage()
+ );
+ }
+
+ public function testFailsWhenCannotRewindRetry()
+ {
+ $res = CurlFactory::createResponse(function () {}, [
+ 'body' => new NoSeekStream(Stream::factory('foo'))
+ ], [], [], null);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Exception\RingException', $res['error']);
+ $this->assertContains(
+ 'rewind the request body failed',
+ $res['error']->getMessage()
+ );
+ }
+
+ public function testRetriesWhenBodyCanBeRewound()
+ {
+ $callHandler = $called = false;
+ $res = CurlFactory::createResponse(function () use (&$callHandler) {
+ $callHandler = true;
+ return ['status' => 200];
+ }, [
+ 'body' => FnStream::decorate(Stream::factory('test'), [
+ 'seek' => function () use (&$called) {
+ $called = true;
+ return true;
+ }
+ ])
+ ], [], [], null);
+
+ $this->assertTrue($callHandler);
+ $this->assertTrue($called);
+ $this->assertEquals('200', $res['status']);
+ }
+
+ public function testFailsWhenRetryMoreThanThreeTimes()
+ {
+ $call = 0;
+ $mock = new MockHandler(function (array $request) use (&$mock, &$call) {
+ $call++;
+ return CurlFactory::createResponse($mock, $request, [], [], null);
+ });
+ $response = $mock([
+ 'http_method' => 'GET',
+ 'body' => 'test',
+ ]);
+ $this->assertEquals(3, $call);
+ $this->assertArrayHasKey('error', $response);
+ $this->assertContains(
+ 'The cURL request was retried 3 times',
+ $response['error']->getMessage()
+ );
+ }
+
+ public function testHandles100Continue()
+ {
+ Server::flush();
+ Server::enqueue([
+ [
+ 'status' => '200',
+ 'reason' => 'OK',
+ 'headers' => [
+ 'Test' => ['Hello'],
+ 'Content-Length' => ['4'],
+ ],
+ 'body' => 'test',
+ ],
+ ]);
+
+ $request = [
+ 'http_method' => 'PUT',
+ 'headers' => [
+ 'Host' => [Server::$host],
+ 'Expect' => ['100-Continue'],
+ ],
+ 'body' => 'test',
+ ];
+
+ $handler = new CurlMultiHandler();
+ $response = $handler($request)->wait();
+ $this->assertEquals(200, $response['status']);
+ $this->assertEquals('OK', $response['reason']);
+ $this->assertEquals(['Hello'], $response['headers']['Test']);
+ $this->assertEquals(['4'], $response['headers']['Content-Length']);
+ $this->assertEquals('test', Core::body($response));
+ }
+
+ public function testCreatesConnectException()
+ {
+ $m = new \ReflectionMethod('GuzzleHttp\Ring\Client\CurlFactory', 'createErrorResponse');
+ $m->setAccessible(true);
+ $response = $m->invoke(
+ null,
+ function () {},
+ [],
+ [
+ 'err_message' => 'foo',
+ 'curl' => [
+ 'errno' => CURLE_COULDNT_CONNECT,
+ ]
+ ]
+ );
+ $this->assertInstanceOf('GuzzleHttp\Ring\Exception\ConnectException', $response['error']);
+ }
+
+ public function testParsesLastResponseOnly()
+ {
+ $response1 = [
+ 'status' => 301,
+ 'headers' => [
+ 'Content-Length' => ['0'],
+ 'Location' => ['/foo']
+ ]
+ ];
+
+ $response2 = [
+ 'status' => 200,
+ 'headers' => [
+ 'Content-Length' => ['0'],
+ 'Foo' => ['bar']
+ ]
+ ];
+
+ Server::flush();
+ Server::enqueue([$response1, $response2]);
+
+ $a = new CurlMultiHandler();
+ $response = $a([
+ 'http_method' => 'GET',
+ 'headers' => ['Host' => [Server::$host]],
+ 'client' => [
+ 'curl' => [
+ CURLOPT_FOLLOWLOCATION => true
+ ]
+ ]
+ ])->wait();
+
+ $this->assertEquals(1, $response['transfer_stats']['redirect_count']);
+ $this->assertEquals('http://127.0.0.1:8125/foo', $response['effective_url']);
+ $this->assertEquals(['bar'], $response['headers']['Foo']);
+ $this->assertEquals(200, $response['status']);
+ $this->assertFalse(Core::hasHeader($response, 'Location'));
+ }
+
+ public function testMaintainsMultiHeaderOrder()
+ {
+ Server::flush();
+ Server::enqueue([
+ [
+ 'status' => 200,
+ 'headers' => [
+ 'Content-Length' => ['0'],
+ 'Foo' => ['a', 'b'],
+ 'foo' => ['c', 'd'],
+ ]
+ ]
+ ]);
+
+ $a = new CurlMultiHandler();
+ $response = $a([
+ 'http_method' => 'GET',
+ 'headers' => ['Host' => [Server::$host]]
+ ])->wait();
+
+ $this->assertEquals(
+ ['a', 'b', 'c', 'd'],
+ Core::headerLines($response, 'Foo')
+ );
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Directory /path/to/does/not does not exist for save_to value of /path/to/does/not/exist.txt
+ */
+ public function testThrowsWhenDirNotFound()
+ {
+ $request = [
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$url]],
+ 'client' => ['save_to' => '/path/to/does/not/exist.txt'],
+ ];
+
+ $f = new CurlFactory();
+ $f($request);
+ }
+}
+
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/CurlHandlerTest.php b/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/CurlHandlerTest.php
new file mode 100644
index 00000000..ba03b8cd
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/CurlHandlerTest.php
@@ -0,0 +1,96 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Client;
+
+use GuzzleHttp\Ring\Client\CurlHandler;
+
+class CurlHandlerTest extends \PHPUnit_Framework_TestCase
+{
+ protected function setUp()
+ {
+ if (!function_exists('curl_reset')) {
+ $this->markTestSkipped('curl_reset() is not available');
+ }
+ }
+
+ protected function getHandler($factory = null, $options = [])
+ {
+ return new CurlHandler($options);
+ }
+
+ public function testCanSetMaxHandles()
+ {
+ $a = new CurlHandler(['max_handles' => 10]);
+ $this->assertEquals(10, $this->readAttribute($a, 'maxHandles'));
+ }
+
+ public function testCreatesCurlErrors()
+ {
+ $handler = new CurlHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['host' => ['localhost:123']],
+ 'client' => ['timeout' => 0.001, 'connect_timeout' => 0.001],
+ ]);
+ $this->assertNull($response['status']);
+ $this->assertNull($response['reason']);
+ $this->assertEquals([], $response['headers']);
+ $this->assertInstanceOf(
+ 'GuzzleHttp\Ring\Exception\RingException',
+ $response['error']
+ );
+
+ $this->assertEquals(
+ 1,
+ preg_match('/^cURL error \d+: .*$/', $response['error']->getMessage())
+ );
+ }
+
+ public function testReleasesAdditionalEasyHandles()
+ {
+ Server::flush();
+ $response = [
+ 'status' => 200,
+ 'headers' => ['Content-Length' => [4]],
+ 'body' => 'test',
+ ];
+
+ Server::enqueue([$response, $response, $response, $response]);
+ $a = new CurlHandler(['max_handles' => 2]);
+
+ $fn = function () use (&$calls, $a, &$fn) {
+ if (++$calls < 4) {
+ $a([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['progress' => $fn],
+ ]);
+ }
+ };
+
+ $request = [
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => [
+ 'progress' => $fn,
+ ],
+ ];
+
+ $a($request);
+ $this->assertCount(2, $this->readAttribute($a, 'handles'));
+ }
+
+ public function testReusesHandles()
+ {
+ Server::flush();
+ $response = ['status' => 200];
+ Server::enqueue([$response, $response]);
+ $a = new CurlHandler();
+ $request = [
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ ];
+ $a($request);
+ $a($request);
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/CurlMultiHandlerTest.php b/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/CurlMultiHandlerTest.php
new file mode 100644
index 00000000..530b2394
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/CurlMultiHandlerTest.php
@@ -0,0 +1,181 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Client;
+
+use GuzzleHttp\Ring\Client\CurlMultiHandler;
+
+class CurlMultiHandlerTest extends \PHPUnit_Framework_TestCase
+{
+ public function testSendsRequest()
+ {
+ Server::enqueue([['status' => 200]]);
+ $a = new CurlMultiHandler();
+ $response = $a([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ ]);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
+ $this->assertEquals(200, $response['status']);
+ $this->assertArrayHasKey('transfer_stats', $response);
+ $realUrl = trim($response['transfer_stats']['url'], '/');
+ $this->assertEquals(trim(Server::$url, '/'), $realUrl);
+ $this->assertArrayHasKey('effective_url', $response);
+ $this->assertEquals(
+ trim(Server::$url, '/'),
+ trim($response['effective_url'], '/')
+ );
+ }
+
+ public function testCreatesErrorResponses()
+ {
+ $url = 'http://localhost:123/';
+ $a = new CurlMultiHandler();
+ $response = $a([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['localhost:123']],
+ ]);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
+ $this->assertNull($response['status']);
+ $this->assertNull($response['reason']);
+ $this->assertEquals([], $response['headers']);
+ $this->assertArrayHasKey('error', $response);
+ $this->assertContains('cURL error ', $response['error']->getMessage());
+ $this->assertArrayHasKey('transfer_stats', $response);
+ $this->assertEquals(
+ trim($url, '/'),
+ trim($response['transfer_stats']['url'], '/')
+ );
+ $this->assertArrayHasKey('effective_url', $response);
+ $this->assertEquals(
+ trim($url, '/'),
+ trim($response['effective_url'], '/')
+ );
+ }
+
+ public function testSendsFuturesWhenDestructed()
+ {
+ Server::enqueue([['status' => 200]]);
+ $a = new CurlMultiHandler();
+ $response = $a([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ ]);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
+ $a->__destruct();
+ $this->assertEquals(200, $response['status']);
+ }
+
+ public function testCanSetMaxHandles()
+ {
+ $a = new CurlMultiHandler(['max_handles' => 2]);
+ $this->assertEquals(2, $this->readAttribute($a, 'maxHandles'));
+ }
+
+ public function testCanSetSelectTimeout()
+ {
+ $a = new CurlMultiHandler(['select_timeout' => 2]);
+ $this->assertEquals(2, $this->readAttribute($a, 'selectTimeout'));
+ }
+
+ public function testSendsFuturesWhenMaxHandlesIsReached()
+ {
+ $request = [
+ 'http_method' => 'PUT',
+ 'headers' => ['host' => [Server::$host]],
+ 'future' => 'lazy', // passing this to control the test
+ ];
+ $response = ['status' => 200];
+ Server::flush();
+ Server::enqueue([$response, $response, $response]);
+ $a = new CurlMultiHandler(['max_handles' => 3]);
+ for ($i = 0; $i < 5; $i++) {
+ $responses[] = $a($request);
+ }
+ $this->assertCount(3, Server::received());
+ $responses[3]->cancel();
+ $responses[4]->cancel();
+ }
+
+ public function testCanCancel()
+ {
+ Server::flush();
+ $response = ['status' => 200];
+ Server::enqueue(array_fill_keys(range(0, 10), $response));
+ $a = new CurlMultiHandler();
+ $responses = [];
+
+ for ($i = 0; $i < 10; $i++) {
+ $response = $a([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'future' => 'lazy',
+ ]);
+ $response->cancel();
+ $responses[] = $response;
+ }
+
+ $this->assertCount(0, Server::received());
+
+ foreach ($responses as $response) {
+ $this->assertTrue($this->readAttribute($response, 'isRealized'));
+ }
+ }
+
+ public function testCannotCancelFinished()
+ {
+ Server::flush();
+ Server::enqueue([['status' => 200]]);
+ $a = new CurlMultiHandler();
+ $response = $a([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ ]);
+ $response->wait();
+ $response->cancel();
+ }
+
+ public function testDelaysInParallel()
+ {
+ Server::flush();
+ Server::enqueue([['status' => 200]]);
+ $a = new CurlMultiHandler();
+ $expected = microtime(true) + (100 / 1000);
+ $response = $a([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['delay' => 100],
+ ]);
+ $response->wait();
+ $this->assertGreaterThanOrEqual($expected, microtime(true));
+ }
+
+ public function testSendsNonLazyFutures()
+ {
+ $request = [
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'future' => true,
+ ];
+ Server::flush();
+ Server::enqueue([['status' => 202]]);
+ $a = new CurlMultiHandler();
+ $response = $a($request);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
+ $this->assertEquals(202, $response['status']);
+ }
+
+ public function testExtractsErrors()
+ {
+ $request = [
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['127.0.0.1:123']],
+ 'future' => true,
+ ];
+ Server::flush();
+ Server::enqueue([['status' => 202]]);
+ $a = new CurlMultiHandler();
+ $response = $a($request);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
+ $this->assertEquals(CURLE_COULDNT_CONNECT, $response['curl']['errno']);
+ $this->assertNotEmpty($response['curl']['error']);
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/MiddlewareTest.php b/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/MiddlewareTest.php
new file mode 100644
index 00000000..a47bb30b
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/MiddlewareTest.php
@@ -0,0 +1,65 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Client;
+
+use GuzzleHttp\Ring\Client\Middleware;
+use GuzzleHttp\Ring\Future\CompletedFutureArray;
+
+class MiddlewareTest extends \PHPUnit_Framework_TestCase
+{
+ public function testFutureCallsDefaultHandler()
+ {
+ $future = new CompletedFutureArray(['status' => 200]);
+ $calledA = false;
+ $a = function (array $req) use (&$calledA, $future) {
+ $calledA = true;
+ return $future;
+ };
+ $calledB = false;
+ $b = function (array $req) use (&$calledB) { $calledB = true; };
+ $s = Middleware::wrapFuture($a, $b);
+ $s([]);
+ $this->assertTrue($calledA);
+ $this->assertFalse($calledB);
+ }
+
+ public function testFutureCallsStreamingHandler()
+ {
+ $future = new CompletedFutureArray(['status' => 200]);
+ $calledA = false;
+ $a = function (array $req) use (&$calledA) { $calledA = true; };
+ $calledB = false;
+ $b = function (array $req) use (&$calledB, $future) {
+ $calledB = true;
+ return $future;
+ };
+ $s = Middleware::wrapFuture($a, $b);
+ $result = $s(['client' => ['future' => true]]);
+ $this->assertFalse($calledA);
+ $this->assertTrue($calledB);
+ $this->assertSame($future, $result);
+ }
+
+ public function testStreamingCallsDefaultHandler()
+ {
+ $calledA = false;
+ $a = function (array $req) use (&$calledA) { $calledA = true; };
+ $calledB = false;
+ $b = function (array $req) use (&$calledB) { $calledB = true; };
+ $s = Middleware::wrapStreaming($a, $b);
+ $s([]);
+ $this->assertTrue($calledA);
+ $this->assertFalse($calledB);
+ }
+
+ public function testStreamingCallsStreamingHandler()
+ {
+ $calledA = false;
+ $a = function (array $req) use (&$calledA) { $calledA = true; };
+ $calledB = false;
+ $b = function (array $req) use (&$calledB) { $calledB = true; };
+ $s = Middleware::wrapStreaming($a, $b);
+ $s(['client' => ['stream' => true]]);
+ $this->assertFalse($calledA);
+ $this->assertTrue($calledB);
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/MockHandlerTest.php b/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/MockHandlerTest.php
new file mode 100644
index 00000000..26bcd6cd
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/MockHandlerTest.php
@@ -0,0 +1,86 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Client;
+
+use GuzzleHttp\Ring\Client\MockHandler;
+use GuzzleHttp\Ring\Future\FutureArray;
+use React\Promise\Deferred;
+
+class MockHandlerTest extends \PHPUnit_Framework_TestCase
+{
+ public function testReturnsArray()
+ {
+ $mock = new MockHandler(['status' => 200]);
+ $response = $mock([]);
+ $this->assertEquals(200, $response['status']);
+ $this->assertEquals([], $response['headers']);
+ $this->assertNull($response['body']);
+ $this->assertNull($response['reason']);
+ $this->assertNull($response['effective_url']);
+ }
+
+ public function testReturnsFutures()
+ {
+ $deferred = new Deferred();
+ $future = new FutureArray(
+ $deferred->promise(),
+ function () use ($deferred) {
+ $deferred->resolve(['status' => 200]);
+ }
+ );
+ $mock = new MockHandler($future);
+ $response = $mock([]);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
+ $this->assertEquals(200, $response['status']);
+ }
+
+ public function testReturnsFuturesWithThenCall()
+ {
+ $deferred = new Deferred();
+ $future = new FutureArray(
+ $deferred->promise(),
+ function () use ($deferred) {
+ $deferred->resolve(['status' => 200]);
+ }
+ );
+ $mock = new MockHandler($future);
+ $response = $mock([]);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
+ $this->assertEquals(200, $response['status']);
+ $req = null;
+ $promise = $response->then(function ($value) use (&$req) {
+ $req = $value;
+ $this->assertEquals(200, $req['status']);
+ });
+ $this->assertInstanceOf('React\Promise\PromiseInterface', $promise);
+ $this->assertEquals(200, $req['status']);
+ }
+
+ public function testReturnsFuturesAndProxiesCancel()
+ {
+ $c = null;
+ $deferred = new Deferred();
+ $future = new FutureArray(
+ $deferred->promise(),
+ function () {},
+ function () use (&$c) {
+ $c = true;
+ return true;
+ }
+ );
+ $mock = new MockHandler($future);
+ $response = $mock([]);
+ $this->assertInstanceOf('GuzzleHttp\Ring\Future\FutureArray', $response);
+ $response->cancel();
+ $this->assertTrue($c);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Response must be an array or FutureArrayInterface. Found
+ */
+ public function testEnsuresMockIsValid()
+ {
+ $mock = new MockHandler('foo');
+ $mock([]);
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/Server.php b/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/Server.php
new file mode 100644
index 00000000..14665a55
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/Server.php
@@ -0,0 +1,183 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Client;
+
+use GuzzleHttp\Ring\Client\StreamHandler;
+use GuzzleHttp\Ring\Core;
+
+/**
+ * Class uses to control the test webserver.
+ *
+ * Queued responses will be served to requests using a FIFO order. All requests
+ * received by the server are stored on the node.js server and can be retrieved
+ * by calling {@see Server::received()}.
+ *
+ * Mock responses that don't require data to be transmitted over HTTP a great
+ * for testing. Mock response, however, cannot test the actual sending of an
+ * HTTP request using cURL. This test server allows the simulation of any
+ * number of HTTP request response transactions to test the actual sending of
+ * requests over the wire without having to leave an internal network.
+ */
+class Server
+{
+ public static $started;
+ public static $url = 'http://127.0.0.1:8125/';
+ public static $host = '127.0.0.1:8125';
+ public static $port = 8125;
+
+ /**
+ * Flush the received requests from the server
+ * @throws \RuntimeException
+ */
+ public static function flush()
+ {
+ self::send('DELETE', '/guzzle-server/requests');
+ }
+
+ /**
+ * Queue an array of responses or a single response on the server.
+ *
+ * Any currently queued responses will be overwritten. Subsequent requests
+ * on the server will return queued responses in FIFO order.
+ *
+ * @param array $responses An array of responses. The shape of a response
+ * is the shape described in the RingPHP spec.
+ * @throws \Exception
+ */
+ public static function enqueue(array $responses)
+ {
+ $data = [];
+
+ foreach ($responses as $response) {
+ if (!is_array($response)) {
+ throw new \Exception('Each response must be an array');
+ }
+
+ if (isset($response['body'])) {
+ $response['body'] = base64_encode($response['body']);
+ }
+
+ $response += ['headers' => [], 'reason' => '', 'body' => ''];
+ $data[] = $response;
+ }
+
+ self::send('PUT', '/guzzle-server/responses', json_encode($data));
+ }
+
+ /**
+ * Get all of the received requests as a RingPHP request structure.
+ *
+ * @return array
+ * @throws \RuntimeException
+ */
+ public static function received()
+ {
+ if (!self::$started) {
+ return [];
+ }
+
+ $response = self::send('GET', '/guzzle-server/requests');
+ $body = Core::body($response);
+ $result = json_decode($body, true);
+ if ($result === false) {
+ throw new \RuntimeException('Error decoding response: '
+ . json_last_error());
+ }
+
+ foreach ($result as &$res) {
+ if (isset($res['uri'])) {
+ $res['resource'] = $res['uri'];
+ }
+ if (isset($res['query_string'])) {
+ $res['resource'] .= '?' . $res['query_string'];
+ }
+ if (!isset($res['resource'])) {
+ $res['resource'] = '';
+ }
+ // Ensure that headers are all arrays
+ if (isset($res['headers'])) {
+ foreach ($res['headers'] as &$h) {
+ $h = (array) $h;
+ }
+ unset($h);
+ }
+ }
+
+ unset($res);
+ return $result;
+ }
+
+ /**
+ * Stop running the node.js server
+ */
+ public static function stop()
+ {
+ if (self::$started) {
+ self::send('DELETE', '/guzzle-server');
+ }
+
+ self::$started = false;
+ }
+
+ public static function wait($maxTries = 20)
+ {
+ $tries = 0;
+ while (!self::isListening() && ++$tries < $maxTries) {
+ usleep(100000);
+ }
+
+ if (!self::isListening()) {
+ throw new \RuntimeException('Unable to contact node.js server');
+ }
+ }
+
+ public static function start()
+ {
+ if (self::$started) {
+ return;
+ }
+
+ try {
+ self::wait();
+ } catch (\Exception $e) {
+ exec('node ' . __DIR__ . \DIRECTORY_SEPARATOR . 'server.js '
+ . self::$port . ' >> /tmp/server.log 2>&1 &');
+ self::wait();
+ }
+
+ self::$started = true;
+ }
+
+ private static function isListening()
+ {
+ $response = self::send('GET', '/guzzle-server/perf', null, [
+ 'connect_timeout' => 1,
+ 'timeout' => 1
+ ]);
+
+ return !isset($response['error']);
+ }
+
+ private static function send(
+ $method,
+ $path,
+ $body = null,
+ array $client = []
+ ) {
+ $handler = new StreamHandler();
+
+ $request = [
+ 'http_method' => $method,
+ 'uri' => $path,
+ 'request_port' => 8125,
+ 'headers' => ['host' => ['127.0.0.1:8125']],
+ 'body' => $body,
+ 'client' => $client,
+ ];
+
+ if ($body) {
+ $request['headers']['content-length'] = [strlen($body)];
+ }
+
+ return $handler($request);
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/StreamHandlerTest.php b/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/StreamHandlerTest.php
new file mode 100644
index 00000000..3cb9a8e1
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/StreamHandlerTest.php
@@ -0,0 +1,480 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Client;
+
+use GuzzleHttp\Ring\Client\ClientUtils;
+use GuzzleHttp\Ring\Core;
+use GuzzleHttp\Ring\Client\StreamHandler;
+
+class StreamHandlerTest extends \PHPUnit_Framework_TestCase
+{
+ public function testReturnsResponseForSuccessfulRequest()
+ {
+ $this->queueRes();
+ $handler = new StreamHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => [
+ 'host' => [Server::$host],
+ 'Foo' => ['Bar'],
+ ],
+ ]);
+
+ $this->assertEquals('1.1', $response['version']);
+ $this->assertEquals(200, $response['status']);
+ $this->assertEquals('OK', $response['reason']);
+ $this->assertEquals(['Bar'], $response['headers']['Foo']);
+ $this->assertEquals(['8'], $response['headers']['Content-Length']);
+ $this->assertEquals('hi there', Core::body($response));
+
+ $sent = Server::received()[0];
+ $this->assertEquals('GET', $sent['http_method']);
+ $this->assertEquals('/', $sent['resource']);
+ $this->assertEquals(['127.0.0.1:8125'], $sent['headers']['host']);
+ $this->assertEquals('Bar', Core::header($sent, 'foo'));
+ }
+
+ public function testAddsErrorToResponse()
+ {
+ $handler = new StreamHandler();
+ $result = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => ['localhost:123']],
+ 'client' => ['timeout' => 0.01],
+ ]);
+ $this->assertInstanceOf(
+ 'GuzzleHttp\Ring\Future\CompletedFutureArray',
+ $result
+ );
+ $this->assertNull($result['status']);
+ $this->assertNull($result['body']);
+ $this->assertEquals([], $result['headers']);
+ $this->assertInstanceOf(
+ 'GuzzleHttp\Ring\Exception\RingException',
+ $result['error']
+ );
+ }
+
+ public function testEnsuresTheHttpProtocol()
+ {
+ $handler = new StreamHandler();
+ $result = $handler([
+ 'http_method' => 'GET',
+ 'url' => 'ftp://localhost:123',
+ ]);
+ $this->assertArrayHasKey('error', $result);
+ $this->assertContains(
+ 'URL is invalid: ftp://localhost:123',
+ $result['error']->getMessage()
+ );
+ }
+
+ public function testStreamAttributeKeepsStreamOpen()
+ {
+ $this->queueRes();
+ $handler = new StreamHandler();
+ $response = $handler([
+ 'http_method' => 'PUT',
+ 'uri' => '/foo',
+ 'query_string' => 'baz=bar',
+ 'headers' => [
+ 'host' => [Server::$host],
+ 'Foo' => ['Bar'],
+ ],
+ 'body' => 'test',
+ 'client' => ['stream' => true],
+ ]);
+
+ $this->assertEquals(200, $response['status']);
+ $this->assertEquals('OK', $response['reason']);
+ $this->assertEquals('8', Core::header($response, 'Content-Length'));
+ $body = $response['body'];
+ $this->assertTrue(is_resource($body));
+ $this->assertEquals('http', stream_get_meta_data($body)['wrapper_type']);
+ $this->assertEquals('hi there', stream_get_contents($body));
+ fclose($body);
+ $sent = Server::received()[0];
+ $this->assertEquals('PUT', $sent['http_method']);
+ $this->assertEquals('/foo', $sent['uri']);
+ $this->assertEquals('baz=bar', $sent['query_string']);
+ $this->assertEquals('/foo?baz=bar', $sent['resource']);
+ $this->assertEquals('127.0.0.1:8125', Core::header($sent, 'host'));
+ $this->assertEquals('Bar', Core::header($sent, 'foo'));
+ }
+
+ public function testDrainsResponseIntoTempStream()
+ {
+ $this->queueRes();
+ $handler = new StreamHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['host' => [Server::$host]],
+ ]);
+ $body = $response['body'];
+ $this->assertEquals('php://temp', stream_get_meta_data($body)['uri']);
+ $this->assertEquals('hi', fread($body, 2));
+ fclose($body);
+ }
+
+ public function testDrainsResponseIntoSaveToBody()
+ {
+ $r = fopen('php://temp', 'r+');
+ $this->queueRes();
+ $handler = new StreamHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['save_to' => $r],
+ ]);
+ $body = $response['body'];
+ $this->assertEquals('php://temp', stream_get_meta_data($body)['uri']);
+ $this->assertEquals('hi', fread($body, 2));
+ $this->assertEquals(' there', stream_get_contents($r));
+ fclose($r);
+ }
+
+ public function testDrainsResponseIntoSaveToBodyAtPath()
+ {
+ $tmpfname = tempnam('/tmp', 'save_to_path');
+ $this->queueRes();
+ $handler = new StreamHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => ['save_to' => $tmpfname],
+ ]);
+ $body = $response['body'];
+ $this->assertInstanceOf('GuzzleHttp\Stream\StreamInterface', $body);
+ $this->assertEquals($tmpfname, $body->getMetadata('uri'));
+ $this->assertEquals('hi', $body->read(2));
+ $body->close();
+ unlink($tmpfname);
+ }
+
+ public function testAutomaticallyDecompressGzip()
+ {
+ Server::flush();
+ $content = gzencode('test');
+ Server::enqueue([
+ [
+ 'status' => 200,
+ 'reason' => 'OK',
+ 'headers' => [
+ 'Content-Encoding' => ['gzip'],
+ 'Content-Length' => [strlen($content)],
+ ],
+ 'body' => $content,
+ ],
+ ]);
+
+ $handler = new StreamHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'uri' => '/',
+ 'client' => ['decode_content' => true],
+ ]);
+ $this->assertEquals('test', Core::body($response));
+ }
+
+ public function testDoesNotForceGzipDecode()
+ {
+ Server::flush();
+ $content = gzencode('test');
+ Server::enqueue([
+ [
+ 'status' => 200,
+ 'reason' => 'OK',
+ 'headers' => [
+ 'Content-Encoding' => ['gzip'],
+ 'Content-Length' => [strlen($content)],
+ ],
+ 'body' => $content,
+ ],
+ ]);
+
+ $handler = new StreamHandler();
+ $response = $handler([
+ 'http_method' => 'GET',
+ 'headers' => ['host' => [Server::$host]],
+ 'uri' => '/',
+ 'client' => ['stream' => true, 'decode_content' => false],
+ ]);
+ $this->assertSame($content, Core::body($response));
+ }
+
+ public function testProtocolVersion()
+ {
+ $this->queueRes();
+ $handler = new StreamHandler();
+ $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['host' => [Server::$host]],
+ 'version' => 1.0,
+ ]);
+
+ $this->assertEquals(1.0, Server::received()[0]['version']);
+ }
+
+ protected function getSendResult(array $opts)
+ {
+ $this->queueRes();
+ $handler = new StreamHandler();
+ $opts['stream'] = true;
+ return $handler([
+ 'http_method' => 'GET',
+ 'uri' => '/',
+ 'headers' => ['host' => [Server::$host]],
+ 'client' => $opts,
+ ]);
+ }
+
+ public function testAddsProxy()
+ {
+ $res = $this->getSendResult(['stream' => true, 'proxy' => '127.0.0.1:8125']);
+ $opts = stream_context_get_options($res['body']);
+ $this->assertEquals('127.0.0.1:8125', $opts['http']['proxy']);
+ }
+
+ public function testAddsTimeout()
+ {
+ $res = $this->getSendResult(['stream' => true, 'timeout' => 200]);
+ $opts = stream_context_get_options($res['body']);
+ $this->assertEquals(200, $opts['http']['timeout']);
+ }
+
+ public function testVerifiesVerifyIsValidIfPath()
+ {
+ $res = $this->getSendResult(['verify' => '/does/not/exist']);
+ $this->assertContains(
+ 'SSL CA bundle not found: /does/not/exist',
+ (string) $res['error']
+ );
+ }
+
+ public function testVerifyCanBeDisabled()
+ {
+ $res = $this->getSendResult(['verify' => false]);
+ $this->assertArrayNotHasKey('error', $res);
+ }
+
+ public function testVerifiesCertIfValidPath()
+ {
+ $res = $this->getSendResult(['cert' => '/does/not/exist']);
+ $this->assertContains(
+ 'SSL certificate not found: /does/not/exist',
+ (string) $res['error']
+ );
+ }
+
+ public function testVerifyCanBeSetToPath()
+ {
+ $path = $path = ClientUtils::getDefaultCaBundle();
+ $res = $this->getSendResult(['verify' => $path]);
+ $this->assertArrayNotHasKey('error', $res);
+ $opts = stream_context_get_options($res['body']);
+ $this->assertEquals(true, $opts['ssl']['verify_peer']);
+ $this->assertEquals($path, $opts['ssl']['cafile']);
+ $this->assertTrue(file_exists($opts['ssl']['cafile']));
+ }
+
+ public function testUsesSystemDefaultBundle()
+ {
+ $path = $path = ClientUtils::getDefaultCaBundle();
+ $res = $this->getSendResult(['verify' => true]);
+ $this->assertArrayNotHasKey('error', $res);
+ $opts = stream_context_get_options($res['body']);
+ if (PHP_VERSION_ID < 50600) {
+ $this->assertEquals($path, $opts['ssl']['cafile']);
+ }
+ }
+
+ public function testEnsuresVerifyOptionIsValid()
+ {
+ $res = $this->getSendResult(['verify' => 10]);
+ $this->assertContains(
+ 'Invalid verify request option',
+ (string) $res['error']
+ );
+ }
+
+ public function testCanSetPasswordWhenSettingCert()
+ {
+ $path = __FILE__;
+ $res = $this->getSendResult(['cert' => [$path, 'foo']]);
+ $opts = stream_context_get_options($res['body']);
+ $this->assertEquals($path, $opts['ssl']['local_cert']);
+ $this->assertEquals('foo', $opts['ssl']['passphrase']);
+ }
+
+ public function testDebugAttributeWritesToStream()
+ {
+ $this->queueRes();
+ $f = fopen('php://temp', 'w+');
+ $this->getSendResult(['debug' => $f]);
+ fseek($f, 0);
+ $contents = stream_get_contents($f);
+ $this->assertContains('<GET http://127.0.0.1:8125/> [CONNECT]', $contents);
+ $this->assertContains('<GET http://127.0.0.1:8125/> [FILE_SIZE_IS]', $contents);
+ $this->assertContains('<GET http://127.0.0.1:8125/> [PROGRESS]', $contents);
+ }
+
+ public function testDebugAttributeWritesStreamInfoToBuffer()
+ {
+ $called = false;
+ $this->queueRes();
+ $buffer = fopen('php://temp', 'r+');
+ $this->getSendResult([
+ 'progress' => function () use (&$called) { $called = true; },
+ 'debug' => $buffer,
+ ]);
+ fseek($buffer, 0);
+ $contents = stream_get_contents($buffer);
+ $this->assertContains('<GET http://127.0.0.1:8125/> [CONNECT]', $contents);
+ $this->assertContains('<GET http://127.0.0.1:8125/> [FILE_SIZE_IS] message: "Content-Length: 8"', $contents);
+ $this->assertContains('<GET http://127.0.0.1:8125/> [PROGRESS] bytes_max: "8"', $contents);
+ $this->assertTrue($called);
+ }
+
+ public function testEmitsProgressInformation()
+ {
+ $called = [];
+ $this->queueRes();
+ $this->getSendResult([
+ 'progress' => function () use (&$called) {
+ $called[] = func_get_args();
+ },
+ ]);
+ $this->assertNotEmpty($called);
+ $this->assertEquals(8, $called[0][0]);
+ $this->assertEquals(0, $called[0][1]);
+ }
+
+ public function testEmitsProgressInformationAndDebugInformation()
+ {
+ $called = [];
+ $this->queueRes();
+ $buffer = fopen('php://memory', 'w+');
+ $this->getSendResult([
+ 'debug' => $buffer,
+ 'progress' => function () use (&$called) {
+ $called[] = func_get_args();
+ },
+ ]);
+ $this->assertNotEmpty($called);
+ $this->assertEquals(8, $called[0][0]);
+ $this->assertEquals(0, $called[0][1]);
+ rewind($buffer);
+ $this->assertNotEmpty(stream_get_contents($buffer));
+ fclose($buffer);
+ }
+
+ public function testAddsProxyByProtocol()
+ {
+ $url = str_replace('http', 'tcp', Server::$url);
+ $res = $this->getSendResult(['proxy' => ['http' => $url]]);
+ $opts = stream_context_get_options($res['body']);
+ $this->assertEquals($url, $opts['http']['proxy']);
+ }
+
+ public function testPerformsShallowMergeOfCustomContextOptions()
+ {
+ $res = $this->getSendResult([
+ 'stream_context' => [
+ 'http' => [
+ 'request_fulluri' => true,
+ 'method' => 'HEAD',
+ ],
+ 'socket' => [
+ 'bindto' => '127.0.0.1:0',
+ ],
+ 'ssl' => [
+ 'verify_peer' => false,
+ ],
+ ],
+ ]);
+
+ $opts = stream_context_get_options($res['body']);
+ $this->assertEquals('HEAD', $opts['http']['method']);
+ $this->assertTrue($opts['http']['request_fulluri']);
+ $this->assertFalse($opts['ssl']['verify_peer']);
+ $this->assertEquals('127.0.0.1:0', $opts['socket']['bindto']);
+ }
+
+ public function testEnsuresThatStreamContextIsAnArray()
+ {
+ $res = $this->getSendResult(['stream_context' => 'foo']);
+ $this->assertContains(
+ 'stream_context must be an array',
+ (string) $res['error']
+ );
+ }
+
+ public function testDoesNotAddContentTypeByDefault()
+ {
+ $this->queueRes();
+ $handler = new StreamHandler();
+ $handler([
+ 'http_method' => 'PUT',
+ 'uri' => '/',
+ 'headers' => ['host' => [Server::$host], 'content-length' => [3]],
+ 'body' => 'foo',
+ ]);
+ $req = Server::received()[0];
+ $this->assertEquals('', Core::header($req, 'Content-Type'));
+ $this->assertEquals(3, Core::header($req, 'Content-Length'));
+ }
+
+ private function queueRes()
+ {
+ Server::flush();
+ Server::enqueue([
+ [
+ 'status' => 200,
+ 'reason' => 'OK',
+ 'headers' => [
+ 'Foo' => ['Bar'],
+ 'Content-Length' => [8],
+ ],
+ 'body' => 'hi there',
+ ],
+ ]);
+ }
+
+ public function testSupports100Continue()
+ {
+ Server::flush();
+ Server::enqueue([
+ [
+ 'status' => '200',
+ 'reason' => 'OK',
+ 'headers' => [
+ 'Test' => ['Hello'],
+ 'Content-Length' => ['4'],
+ ],
+ 'body' => 'test',
+ ],
+ ]);
+
+ $request = [
+ 'http_method' => 'PUT',
+ 'headers' => [
+ 'Host' => [Server::$host],
+ 'Expect' => ['100-Continue'],
+ ],
+ 'body' => 'test',
+ ];
+
+ $handler = new StreamHandler();
+ $response = $handler($request);
+ $this->assertEquals(200, $response['status']);
+ $this->assertEquals('OK', $response['reason']);
+ $this->assertEquals(['Hello'], $response['headers']['Test']);
+ $this->assertEquals(['4'], $response['headers']['Content-Length']);
+ $this->assertEquals('test', Core::body($response));
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/server.js b/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/server.js
new file mode 100644
index 00000000..6a03e33a
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/tests/Client/server.js
@@ -0,0 +1,241 @@
+/**
+ * Guzzle node.js test server to return queued responses to HTTP requests and
+ * expose a RESTful API for enqueueing responses and retrieving the requests
+ * that have been received.
+ *
+ * - Delete all requests that have been received:
+ * > DELETE /guzzle-server/requests
+ * > Host: 127.0.0.1:8125
+ *
+ * - Enqueue responses
+ * > PUT /guzzle-server/responses
+ * > Host: 127.0.0.1:8125
+ * >
+ * > [{'status': 200, 'reason': 'OK', 'headers': {}, 'body': '' }]
+ *
+ * - Get the received requests
+ * > GET /guzzle-server/requests
+ * > Host: 127.0.0.1:8125
+ *
+ * < HTTP/1.1 200 OK
+ * <
+ * < [{'http_method': 'GET', 'uri': '/', 'headers': {}, 'body': 'string'}]
+ *
+ * - Attempt access to the secure area
+ * > GET /secure/by-digest/qop-auth/guzzle-server/requests
+ * > Host: 127.0.0.1:8125
+ *
+ * < HTTP/1.1 401 Unauthorized
+ * < WWW-Authenticate: Digest realm="Digest Test", qop="auth", nonce="0796e98e1aeef43141fab2a66bf4521a", algorithm="MD5", stale="false"
+ * <
+ * < 401 Unauthorized
+ *
+ * - Shutdown the server
+ * > DELETE /guzzle-server
+ * > Host: 127.0.0.1:8125
+ *
+ * @package Guzzle PHP <http://www.guzzlephp.org>
+ * @license See the LICENSE file that was distributed with this source code.
+ */
+
+var http = require('http');
+var url = require('url');
+
+/**
+ * Guzzle node.js server
+ * @class
+ */
+var GuzzleServer = function(port, log) {
+
+ this.port = port;
+ this.log = log;
+ this.responses = [];
+ this.requests = [];
+ var that = this;
+
+ var md5 = function(input) {
+ var crypto = require('crypto');
+ var hasher = crypto.createHash('md5');
+ hasher.update(input);
+ return hasher.digest('hex');
+ }
+
+ /**
+ * Node.js HTTP server authentication module.
+ *
+ * It is only initialized on demand (by loadAuthentifier). This avoids
+ * requiring the dependency to http-auth on standard operations, and the
+ * performance hit at startup.
+ */
+ var auth;
+
+ /**
+ * Provides authentication handlers (Basic, Digest).
+ */
+ var loadAuthentifier = function(type, options) {
+ var typeId = type;
+ if (type == 'digest') {
+ typeId += '.'+(options && options.qop ? options.qop : 'none');
+ }
+ if (!loadAuthentifier[typeId]) {
+ if (!auth) {
+ try {
+ auth = require('http-auth');
+ } catch (e) {
+ if (e.code == 'MODULE_NOT_FOUND') {
+ return;
+ }
+ }
+ }
+ switch (type) {
+ case 'digest':
+ var digestParams = {
+ realm: 'Digest Test',
+ login: 'me',
+ password: 'test'
+ };
+ if (options && options.qop) {
+ digestParams.qop = options.qop;
+ }
+ loadAuthentifier[typeId] = auth.digest(digestParams, function(username, callback) {
+ callback(md5(digestParams.login + ':' + digestParams.realm + ':' + digestParams.password));
+ });
+ break
+ }
+ }
+ return loadAuthentifier[typeId];
+ };
+
+ var firewallRequest = function(request, req, res, requestHandlerCallback) {
+ var securedAreaUriParts = request.uri.match(/^\/secure\/by-(digest)(\/qop-([^\/]*))?(\/.*)$/);
+ if (securedAreaUriParts) {
+ var authentifier = loadAuthentifier(securedAreaUriParts[1], { qop: securedAreaUriParts[2] });
+ if (!authentifier) {
+ res.writeHead(501, 'HTTP authentication not implemented', { 'Content-Length': 0 });
+ res.end();
+ return;
+ }
+ authentifier.check(req, res, function(req, res) {
+ req.url = securedAreaUriParts[4];
+ requestHandlerCallback(request, req, res);
+ });
+ } else {
+ requestHandlerCallback(request, req, res);
+ }
+ };
+
+ var controlRequest = function(request, req, res) {
+ if (req.url == '/guzzle-server/perf') {
+ res.writeHead(200, 'OK', {'Content-Length': 16});
+ res.end('Body of response');
+ } else if (req.method == 'DELETE') {
+ if (req.url == '/guzzle-server/requests') {
+ // Clear the received requests
+ that.requests = [];
+ res.writeHead(200, 'OK', { 'Content-Length': 0 });
+ res.end();
+ if (that.log) {
+ console.log('Flushing requests');
+ }
+ } else if (req.url == '/guzzle-server') {
+ // Shutdown the server
+ res.writeHead(200, 'OK', { 'Content-Length': 0, 'Connection': 'close' });
+ res.end();
+ if (that.log) {
+ console.log('Shutting down');
+ }
+ that.server.close();
+ }
+ } else if (req.method == 'GET') {
+ if (req.url === '/guzzle-server/requests') {
+ if (that.log) {
+ console.log('Sending received requests');
+ }
+ // Get received requests
+ var body = JSON.stringify(that.requests);
+ res.writeHead(200, 'OK', { 'Content-Length': body.length });
+ res.end(body);
+ }
+ } else if (req.method == 'PUT' && req.url == '/guzzle-server/responses') {
+ if (that.log) {
+ console.log('Adding responses...');
+ }
+ if (!request.body) {
+ if (that.log) {
+ console.log('No response data was provided');
+ }
+ res.writeHead(400, 'NO RESPONSES IN REQUEST', { 'Content-Length': 0 });
+ } else {
+ that.responses = eval('(' + request.body + ')');
+ for (var i = 0; i < that.responses.length; i++) {
+ if (that.responses[i].body) {
+ that.responses[i].body = new Buffer(that.responses[i].body, 'base64');
+ }
+ }
+ if (that.log) {
+ console.log(that.responses);
+ }
+ res.writeHead(200, 'OK', { 'Content-Length': 0 });
+ }
+ res.end();
+ }
+ };
+
+ var receivedRequest = function(request, req, res) {
+ if (req.url.indexOf('/guzzle-server') === 0) {
+ controlRequest(request, req, res);
+ } else if (req.url.indexOf('/guzzle-server') == -1 && !that.responses.length) {
+ res.writeHead(500);
+ res.end('No responses in queue');
+ } else {
+ if (that.log) {
+ console.log('Returning response from queue and adding request');
+ }
+ that.requests.push(request);
+ var response = that.responses.shift();
+ res.writeHead(response.status, response.reason, response.headers);
+ res.end(response.body);
+ }
+ };
+
+ this.start = function() {
+
+ that.server = http.createServer(function(req, res) {
+
+ var parts = url.parse(req.url, false);
+ var request = {
+ http_method: req.method,
+ scheme: parts.scheme,
+ uri: parts.pathname,
+ query_string: parts.query,
+ headers: req.headers,
+ version: req.httpVersion,
+ body: ''
+ };
+
+ // Receive each chunk of the request body
+ req.addListener('data', function(chunk) {
+ request.body += chunk;
+ });
+
+ // Called when the request completes
+ req.addListener('end', function() {
+ firewallRequest(request, req, res, receivedRequest);
+ });
+ });
+
+ that.server.listen(this.port, '127.0.0.1');
+
+ if (this.log) {
+ console.log('Server running at http://127.0.0.1:8125/');
+ }
+ };
+};
+
+// Get the port from the arguments
+port = process.argv.length >= 3 ? process.argv[2] : 8125;
+log = process.argv.length >= 4 ? process.argv[3] : false;
+
+// Start the server
+server = new GuzzleServer(port, log);
+server.start();
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/tests/CoreTest.php b/www/wiki/vendor/guzzlehttp/ringphp/tests/CoreTest.php
new file mode 100644
index 00000000..49522f26
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/tests/CoreTest.php
@@ -0,0 +1,336 @@
+<?php
+namespace GuzzleHttp\Tests\Ring;
+
+use GuzzleHttp\Ring\Core;
+use GuzzleHttp\Ring\Future\CompletedFutureArray;
+use GuzzleHttp\Ring\Future\FutureArray;
+use GuzzleHttp\Stream\Stream;
+use React\Promise\Deferred;
+
+class CoreTest extends \PHPUnit_Framework_TestCase
+{
+ public function testReturnsNullNoHeadersAreSet()
+ {
+ $this->assertNull(Core::header([], 'Foo'));
+ $this->assertNull(Core::firstHeader([], 'Foo'));
+ }
+
+ public function testChecksIfHasHeader()
+ {
+ $message = [
+ 'headers' => [
+ 'Foo' => ['Bar', 'Baz'],
+ 'foo' => ['hello'],
+ 'bar' => ['1']
+ ]
+ ];
+ $this->assertTrue(Core::hasHeader($message, 'Foo'));
+ $this->assertTrue(Core::hasHeader($message, 'foo'));
+ $this->assertTrue(Core::hasHeader($message, 'FoO'));
+ $this->assertTrue(Core::hasHeader($message, 'bar'));
+ $this->assertFalse(Core::hasHeader($message, 'barr'));
+ }
+
+ public function testReturnsFirstHeaderWhenSimple()
+ {
+ $this->assertEquals('Bar', Core::firstHeader([
+ 'headers' => ['Foo' => ['Bar', 'Baz']],
+ ], 'Foo'));
+ }
+
+ public function testReturnsFirstHeaderWhenMultiplePerLine()
+ {
+ $this->assertEquals('Bar', Core::firstHeader([
+ 'headers' => ['Foo' => ['Bar, Baz']],
+ ], 'Foo'));
+ }
+
+ public function testExtractsCaseInsensitiveHeader()
+ {
+ $this->assertEquals(
+ 'hello',
+ Core::header(['headers' => ['foo' => ['hello']]], 'FoO')
+ );
+ }
+
+ public function testExtractsCaseInsensitiveHeaderLines()
+ {
+ $this->assertEquals(
+ ['a', 'b', 'c', 'd'],
+ Core::headerLines([
+ 'headers' => [
+ 'foo' => ['a', 'b'],
+ 'Foo' => ['c', 'd']
+ ]
+ ], 'foo')
+ );
+ }
+
+ public function testExtractsHeaderLines()
+ {
+ $this->assertEquals(
+ ['bar', 'baz'],
+ Core::headerLines([
+ 'headers' => [
+ 'Foo' => ['bar', 'baz'],
+ ],
+ ], 'Foo')
+ );
+ }
+
+ public function testExtractsHeaderAsString()
+ {
+ $this->assertEquals(
+ 'bar, baz',
+ Core::header([
+ 'headers' => [
+ 'Foo' => ['bar', 'baz'],
+ ],
+ ], 'Foo', true)
+ );
+ }
+
+ public function testReturnsNullWhenHeaderNotFound()
+ {
+ $this->assertNull(Core::header(['headers' => []], 'Foo'));
+ }
+
+ public function testRemovesHeaders()
+ {
+ $message = [
+ 'headers' => [
+ 'foo' => ['bar'],
+ 'Foo' => ['bam'],
+ 'baz' => ['123'],
+ ],
+ ];
+
+ $this->assertSame($message, Core::removeHeader($message, 'bam'));
+ $this->assertEquals([
+ 'headers' => ['baz' => ['123']],
+ ], Core::removeHeader($message, 'foo'));
+ }
+
+ public function testCreatesUrl()
+ {
+ $req = [
+ 'scheme' => 'http',
+ 'headers' => ['host' => ['foo.com']],
+ 'uri' => '/',
+ ];
+
+ $this->assertEquals('http://foo.com/', Core::url($req));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage No Host header was provided
+ */
+ public function testEnsuresHostIsAvailableWhenCreatingUrls()
+ {
+ Core::url([]);
+ }
+
+ public function testCreatesUrlWithQueryString()
+ {
+ $req = [
+ 'scheme' => 'http',
+ 'headers' => ['host' => ['foo.com']],
+ 'uri' => '/',
+ 'query_string' => 'foo=baz',
+ ];
+
+ $this->assertEquals('http://foo.com/?foo=baz', Core::url($req));
+ }
+
+ public function testUsesUrlIfSet()
+ {
+ $req = ['url' => 'http://foo.com'];
+ $this->assertEquals('http://foo.com', Core::url($req));
+ }
+
+ public function testReturnsNullWhenNoBody()
+ {
+ $this->assertNull(Core::body([]));
+ }
+
+ public function testReturnsStreamAsString()
+ {
+ $this->assertEquals(
+ 'foo',
+ Core::body(['body' => Stream::factory('foo')])
+ );
+ }
+
+ public function testReturnsString()
+ {
+ $this->assertEquals('foo', Core::body(['body' => 'foo']));
+ }
+
+ public function testReturnsResourceContent()
+ {
+ $r = fopen('php://memory', 'w+');
+ fwrite($r, 'foo');
+ rewind($r);
+ $this->assertEquals('foo', Core::body(['body' => $r]));
+ fclose($r);
+ }
+
+ public function testReturnsIteratorContent()
+ {
+ $a = new \ArrayIterator(['a', 'b', 'cd', '']);
+ $this->assertEquals('abcd', Core::body(['body' => $a]));
+ }
+
+ public function testReturnsObjectToString()
+ {
+ $this->assertEquals('foo', Core::body(['body' => new StrClass]));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testEnsuresBodyIsValid()
+ {
+ Core::body(['body' => false]);
+ }
+
+ public function testParsesHeadersFromLines()
+ {
+ $lines = ['Foo: bar', 'Foo: baz', 'Abc: 123', 'Def: a, b'];
+ $this->assertEquals([
+ 'Foo' => ['bar', 'baz'],
+ 'Abc' => ['123'],
+ 'Def' => ['a, b'],
+ ], Core::headersFromLines($lines));
+ }
+
+ public function testParsesHeadersFromLinesWithMultipleLines()
+ {
+ $lines = ['Foo: bar', 'Foo: baz', 'Foo: 123'];
+ $this->assertEquals([
+ 'Foo' => ['bar', 'baz', '123'],
+ ], Core::headersFromLines($lines));
+ }
+
+ public function testCreatesArrayCallFunctions()
+ {
+ $called = [];
+ $a = function ($a, $b) use (&$called) {
+ $called['a'] = func_get_args();
+ };
+ $b = function ($a, $b) use (&$called) {
+ $called['b'] = func_get_args();
+ };
+ $c = Core::callArray([$a, $b]);
+ $c(1, 2);
+ $this->assertEquals([1, 2], $called['a']);
+ $this->assertEquals([1, 2], $called['b']);
+ }
+
+ public function testRewindsGuzzleStreams()
+ {
+ $str = Stream::factory('foo');
+ $this->assertTrue(Core::rewindBody(['body' => $str]));
+ }
+
+ public function testRewindsStreams()
+ {
+ $str = Stream::factory('foo')->detach();
+ $this->assertTrue(Core::rewindBody(['body' => $str]));
+ }
+
+ public function testRewindsIterators()
+ {
+ $iter = new \ArrayIterator(['foo']);
+ $this->assertTrue(Core::rewindBody(['body' => $iter]));
+ }
+
+ public function testRewindsStrings()
+ {
+ $this->assertTrue(Core::rewindBody(['body' => 'hi']));
+ }
+
+ public function testRewindsToStrings()
+ {
+ $this->assertTrue(Core::rewindBody(['body' => new StrClass()]));
+ }
+
+ public function typeProvider()
+ {
+ return [
+ ['foo', 'string(3) "foo"'],
+ [true, 'bool(true)'],
+ [false, 'bool(false)'],
+ [10, 'int(10)'],
+ [1.0, 'float(1)'],
+ [new StrClass(), 'object(GuzzleHttp\Tests\Ring\StrClass)'],
+ [['foo'], 'array(1)']
+ ];
+ }
+
+ /**
+ * @dataProvider typeProvider
+ */
+ public function testDescribesType($input, $output)
+ {
+ $this->assertEquals($output, Core::describeType($input));
+ }
+
+ public function testDoesSleep()
+ {
+ $t = microtime(true);
+ $expected = $t + (100 / 1000);
+ Core::doSleep(['client' => ['delay' => 100]]);
+ $this->assertGreaterThanOrEqual($expected, microtime(true));
+ }
+
+ public function testProxiesFuture()
+ {
+ $f = new CompletedFutureArray(['status' => 200]);
+ $res = null;
+ $proxied = Core::proxy($f, function ($value) use (&$res) {
+ $value['foo'] = 'bar';
+ $res = $value;
+ return $value;
+ });
+ $this->assertNotSame($f, $proxied);
+ $this->assertEquals(200, $f->wait()['status']);
+ $this->assertArrayNotHasKey('foo', $f->wait());
+ $this->assertEquals('bar', $proxied->wait()['foo']);
+ $this->assertEquals(200, $proxied->wait()['status']);
+ }
+
+ public function testProxiesDeferredFuture()
+ {
+ $d = new Deferred();
+ $f = new FutureArray($d->promise());
+ $f2 = Core::proxy($f);
+ $d->resolve(['foo' => 'bar']);
+ $this->assertEquals('bar', $f['foo']);
+ $this->assertEquals('bar', $f2['foo']);
+ }
+
+ public function testProxiesDeferredFutureFailure()
+ {
+ $d = new Deferred();
+ $f = new FutureArray($d->promise());
+ $f2 = Core::proxy($f);
+ $d->reject(new \Exception('foo'));
+ try {
+ $f2['hello?'];
+ $this->fail('did not throw');
+ } catch (\Exception $e) {
+ $this->assertEquals('foo', $e->getMessage());
+ }
+
+ }
+}
+
+final class StrClass
+{
+ public function __toString()
+ {
+ return 'foo';
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureArrayTest.php b/www/wiki/vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureArrayTest.php
new file mode 100644
index 00000000..82d7efbf
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureArrayTest.php
@@ -0,0 +1,21 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Future;
+
+use GuzzleHttp\Ring\Future\CompletedFutureArray;
+
+class CompletedFutureArrayTest extends \PHPUnit_Framework_TestCase
+{
+ public function testReturnsAsArray()
+ {
+ $f = new CompletedFutureArray(['foo' => 'bar']);
+ $this->assertEquals('bar', $f['foo']);
+ $this->assertFalse(isset($f['baz']));
+ $f['abc'] = '123';
+ $this->assertTrue(isset($f['abc']));
+ $this->assertEquals(['foo' => 'bar', 'abc' => '123'], iterator_to_array($f));
+ $this->assertEquals(2, count($f));
+ unset($f['abc']);
+ $this->assertEquals(1, count($f));
+ $this->assertEquals(['foo' => 'bar'], iterator_to_array($f));
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureValueTest.php b/www/wiki/vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureValueTest.php
new file mode 100644
index 00000000..6ded40df
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/tests/Future/CompletedFutureValueTest.php
@@ -0,0 +1,46 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Future;
+
+use GuzzleHttp\Ring\Exception\CancelledFutureAccessException;
+use GuzzleHttp\Ring\Future\CompletedFutureValue;
+
+class CompletedFutureValueTest extends \PHPUnit_Framework_TestCase
+{
+ public function testReturnsValue()
+ {
+ $f = new CompletedFutureValue('hi');
+ $this->assertEquals('hi', $f->wait());
+ $f->cancel();
+
+ $a = null;
+ $f->then(function ($v) use (&$a) {
+ $a = $v;
+ });
+ $this->assertSame('hi', $a);
+ }
+
+ public function testThrows()
+ {
+ $ex = new \Exception('foo');
+ $f = new CompletedFutureValue(null, $ex);
+ $f->cancel();
+ try {
+ $f->wait();
+ $this->fail('did not throw');
+ } catch (\Exception $e) {
+ $this->assertSame($e, $ex);
+ }
+ }
+
+ public function testMarksAsCancelled()
+ {
+ $ex = new CancelledFutureAccessException();
+ $f = new CompletedFutureValue(null, $ex);
+ try {
+ $f->wait();
+ $this->fail('did not throw');
+ } catch (\Exception $e) {
+ $this->assertSame($e, $ex);
+ }
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/tests/Future/FutureArrayTest.php b/www/wiki/vendor/guzzlehttp/ringphp/tests/Future/FutureArrayTest.php
new file mode 100644
index 00000000..0e09f5af
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/tests/Future/FutureArrayTest.php
@@ -0,0 +1,56 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Future;
+
+use GuzzleHttp\Ring\Future\FutureArray;
+use React\Promise\Deferred;
+
+class FutureArrayTest extends \PHPUnit_Framework_TestCase
+{
+ public function testLazilyCallsDeref()
+ {
+ $c = false;
+ $deferred = new Deferred();
+ $f = new FutureArray(
+ $deferred->promise(),
+ function () use (&$c, $deferred) {
+ $c = true;
+ $deferred->resolve(['status' => 200]);
+ }
+ );
+ $this->assertFalse($c);
+ $this->assertFalse($this->readAttribute($f, 'isRealized'));
+ $this->assertEquals(200, $f['status']);
+ $this->assertTrue($c);
+ }
+
+ public function testActsLikeArray()
+ {
+ $deferred = new Deferred();
+ $f = new FutureArray(
+ $deferred->promise(),
+ function () use (&$c, $deferred) {
+ $deferred->resolve(['status' => 200]);
+ }
+ );
+
+ $this->assertTrue(isset($f['status']));
+ $this->assertEquals(200, $f['status']);
+ $this->assertEquals(['status' => 200], $f->wait());
+ $this->assertEquals(1, count($f));
+ $f['baz'] = 10;
+ $this->assertEquals(10, $f['baz']);
+ unset($f['baz']);
+ $this->assertFalse(isset($f['baz']));
+ $this->assertEquals(['status' => 200], iterator_to_array($f));
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testThrowsWhenAccessingInvalidProperty()
+ {
+ $deferred = new Deferred();
+ $f = new FutureArray($deferred->promise(), function () {});
+ $f->foo;
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/tests/Future/FutureValueTest.php b/www/wiki/vendor/guzzlehttp/ringphp/tests/Future/FutureValueTest.php
new file mode 100644
index 00000000..d59c543d
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/tests/Future/FutureValueTest.php
@@ -0,0 +1,109 @@
+<?php
+namespace GuzzleHttp\Tests\Ring\Future;
+
+use GuzzleHttp\Ring\Exception\CancelledFutureAccessException;
+use GuzzleHttp\Ring\Future\FutureValue;
+use React\Promise\Deferred;
+
+class FutureValueTest extends \PHPUnit_Framework_TestCase
+{
+ public function testDerefReturnsValue()
+ {
+ $called = 0;
+ $deferred = new Deferred();
+
+ $f = new FutureValue(
+ $deferred->promise(),
+ function () use ($deferred, &$called) {
+ $called++;
+ $deferred->resolve('foo');
+ }
+ );
+
+ $this->assertEquals('foo', $f->wait());
+ $this->assertEquals(1, $called);
+ $this->assertEquals('foo', $f->wait());
+ $this->assertEquals(1, $called);
+ $f->cancel();
+ $this->assertTrue($this->readAttribute($f, 'isRealized'));
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Ring\Exception\CancelledFutureAccessException
+ */
+ public function testThrowsWhenAccessingCancelled()
+ {
+ $f = new FutureValue(
+ (new Deferred())->promise(),
+ function () {},
+ function () { return true; }
+ );
+ $f->cancel();
+ $f->wait();
+ }
+
+ /**
+ * @expectedException \OutOfBoundsException
+ */
+ public function testThrowsWhenDerefFailure()
+ {
+ $called = false;
+ $deferred = new Deferred();
+ $f = new FutureValue(
+ $deferred->promise(),
+ function () use(&$called) {
+ $called = true;
+ }
+ );
+ $deferred->reject(new \OutOfBoundsException());
+ $f->wait();
+ $this->assertFalse($called);
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Ring\Exception\RingException
+ * @expectedExceptionMessage Waiting did not resolve future
+ */
+ public function testThrowsWhenDerefDoesNotResolve()
+ {
+ $deferred = new Deferred();
+ $f = new FutureValue(
+ $deferred->promise(),
+ function () use(&$called) {
+ $called = true;
+ }
+ );
+ $f->wait();
+ }
+
+ public function testThrowingCancelledFutureAccessExceptionCancels()
+ {
+ $deferred = new Deferred();
+ $f = new FutureValue(
+ $deferred->promise(),
+ function () use ($deferred) {
+ throw new CancelledFutureAccessException();
+ }
+ );
+ try {
+ $f->wait();
+ $this->fail('did not throw');
+ } catch (CancelledFutureAccessException $e) {}
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage foo
+ */
+ public function testThrowingExceptionInDerefMarksAsFailed()
+ {
+ $deferred = new Deferred();
+ $f = new FutureValue(
+ $deferred->promise(),
+ function () {
+ throw new \Exception('foo');
+ }
+ );
+ $f->wait();
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/ringphp/tests/bootstrap.php b/www/wiki/vendor/guzzlehttp/ringphp/tests/bootstrap.php
new file mode 100644
index 00000000..017610fe
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/ringphp/tests/bootstrap.php
@@ -0,0 +1,11 @@
+<?php
+require __DIR__ . '/../vendor/autoload.php';
+require __DIR__ . '/Client/Server.php';
+
+use GuzzleHttp\Tests\Ring\Client\Server;
+
+Server::start();
+
+register_shutdown_function(function () {
+ Server::stop();
+});
diff --git a/www/wiki/vendor/guzzlehttp/streams/.gitignore b/www/wiki/vendor/guzzlehttp/streams/.gitignore
new file mode 100644
index 00000000..c33d3965
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/.gitignore
@@ -0,0 +1,6 @@
+.idea
+.DS_STORE
+coverage
+phpunit.xml
+composer.lock
+vendor/
diff --git a/www/wiki/vendor/guzzlehttp/streams/.travis.yml b/www/wiki/vendor/guzzlehttp/streams/.travis.yml
new file mode 100644
index 00000000..a6f8a87b
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/.travis.yml
@@ -0,0 +1,17 @@
+language: php
+
+php:
+ - 5.4
+ - 5.5
+ - 5.6
+ - hhvm
+
+before_script:
+ - composer self-update
+ - composer install --no-interaction --prefer-source --dev
+
+script: vendor/bin/phpunit
+
+matrix:
+ allow_failures:
+ - php: hhvm
diff --git a/www/wiki/vendor/guzzlehttp/streams/CHANGELOG.rst b/www/wiki/vendor/guzzlehttp/streams/CHANGELOG.rst
new file mode 100644
index 00000000..0018ffe3
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/CHANGELOG.rst
@@ -0,0 +1,94 @@
+=========
+Changelog
+=========
+
+3.0.0 (2014-10-12)
+------------------
+
+* Now supports creating streams from functions and iterators.
+* Supports creating buffered streams and asynchronous streams.
+* Removed ``functions.php``. Use the corresponding functions provided by
+ ``GuzzleHttp\Streams\Utils`` instead.
+* Moved ``GuzzleHttp\Stream\MetadataStreamInterface::getMetadata`` to
+ ``GuzzleHttp\Stream\StreamInterface``. MetadataStreamInterface is no longer
+ used and is marked as deprecated.
+* Added ``attach()`` to ``GuzzleHttp\Stream\StreamInterface`` for PSR-7
+ compatibility.
+* Removed ``flush()`` from StreamInterface.
+* Removed the ``$maxLength`` parameter from
+ ``GuzzleHttp\Stream\StreamInterface::getContents()``. This function now
+ returns the entire remainder of the stream. If you want to limit the maximum
+ amount of data read from the stream, use the
+ ``GuzzleHttp\Stream\Utils::copyToString()`` function.
+* Streams that return an empty string, ``''``, are no longer considered a
+ failure. You MUST return ``false`` to mark the read as a failure, and ensure
+ that any decorators you create properly return ``true`` in response to the
+ ``eof()`` method when the stream is consumed.
+* ``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.
+* Added ``GuzzleHttp\Stream\BufferStream`` to add support for buffering data,
+ and when read, shifting data off of the buffer.
+* Added ``GuzzleHttp\Stream\NullBuffer`` which can be used as a buffer that
+ does not actually store any data.
+* Added ``GuzzleHttp\Stream\AsyncStream`` to provide support for non-blocking
+ streams that can be filled by a remote source (e.g., an event-loop). If a
+ ``drain`` option is provided, the stream can also act as if it is a blocking
+ stream.
+
+2.1.0 (2014-08-17)
+------------------
+
+* Added an InflateStream to inflate gzipped or deflated content.
+* Added ``flush`` to stream wrapper.
+* Added the ability to easily register the GuzzleStreamWrapper if needed.
+
+2.0.0 (2014-08-16)
+------------------
+
+* Deprecated functions.php and moved all of those methods to
+ ``GuzzleHttp\Streams\Utils``. Use ``GuzzleHttp\Stream\Stream::factory()``
+ instead of ``GuzzleHttp\Stream\create()`` to create new streams.
+* Added ``flush()`` to ``StreamInterface``. This method is used to flush any
+ underlying stream write buffers.
+* Added ``FnStream`` to easily decorate stream behavior with callables.
+* ``Utils::hash`` now throws an exception when the stream cannot seek to 0.
+
+1.5.1 (2014-09-10)
+------------------
+
+* Stream metadata is grabbed from the underlying stream each time
+ ``getMetadata`` is called rather than returning a value from a cache.
+* Properly closing all underlying streams when AppendStream is closed.
+* Seek functions no longer throw exceptions.
+* LazyOpenStream now correctly returns the underlying stream resource when
+ detached.
+
+1.5.0 (2014-08-07)
+------------------
+
+* Added ``Stream\safe_open`` to open stream resources and throw exceptions
+ instead of raising errors.
+
+1.4.0 (2014-07-19)
+------------------
+
+* Added a LazyOpenStream
+
+1.3.0 (2014-07-15)
+------------------
+
+* Added an AppendStream to stream over multiple stream one after the other.
+
+1.2.0 (2014-07-15)
+------------------
+
+* Updated the ``detach()`` method to return the underlying stream resource or
+ ``null`` if it does not wrap a resource.
+* Multiple fixes for how streams behave when the underlying resource is
+ detached
+* Do not clear statcache when a stream does not have a 'uri'
+* Added a fix to LimitStream
+* Added a condition to ensure that functions.php can be required multiple times
diff --git a/www/wiki/vendor/guzzlehttp/streams/LICENSE b/www/wiki/vendor/guzzlehttp/streams/LICENSE
new file mode 100644
index 00000000..71d3b783
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2014 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/www/wiki/vendor/guzzlehttp/streams/Makefile b/www/wiki/vendor/guzzlehttp/streams/Makefile
new file mode 100644
index 00000000..f4d42849
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/Makefile
@@ -0,0 +1,19 @@
+all: clean coverage
+
+release: tag
+ git push origin --tags
+
+tag:
+ chag tag --sign --debug CHANGELOG.rst
+
+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/www/wiki/vendor/guzzlehttp/streams/README.rst b/www/wiki/vendor/guzzlehttp/streams/README.rst
new file mode 100644
index 00000000..baff63b3
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/README.rst
@@ -0,0 +1,36 @@
+==============
+Guzzle Streams
+==============
+
+Provides a simple abstraction over streams of data.
+
+This library is used in `Guzzle 5 <https://github.com/guzzle/guzzle>`_, and is
+(currently) compatible with the WIP PSR-7.
+
+Installation
+============
+
+This package can be installed easily using `Composer <http://getcomposer.org>`_.
+Simply add the following to the composer.json file at the root of your project:
+
+.. code-block:: javascript
+
+ {
+ "require": {
+ "guzzlehttp/streams": "~3.0"
+ }
+ }
+
+Then install your dependencies using ``composer.phar install``.
+
+Documentation
+=============
+
+The documentation for this package can be found on the main Guzzle website at
+http://docs.guzzlephp.org/en/guzzle4/streams.html.
+
+Testing
+=======
+
+This library is tested using PHPUnit. You'll need to install the dependencies
+using `Composer <http://getcomposer.org>`_ then run ``make test``.
diff --git a/www/wiki/vendor/guzzlehttp/streams/composer.json b/www/wiki/vendor/guzzlehttp/streams/composer.json
new file mode 100644
index 00000000..6d703437
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/composer.json
@@ -0,0 +1,28 @@
+{
+ "name": "guzzlehttp/streams",
+ "description": "Provides a simple abstraction over streams of data",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": ["stream", "guzzle"],
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "require": {
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "autoload": {
+ "psr-4": { "GuzzleHttp\\Stream\\": "src/" }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/phpunit.xml.dist b/www/wiki/vendor/guzzlehttp/streams/phpunit.xml.dist
new file mode 100644
index 00000000..6e758c19
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/phpunit.xml.dist
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit bootstrap="./vendor/autoload.php"
+ colors="true">
+ <testsuites>
+ <testsuite>
+ <directory>tests</directory>
+ </testsuite>
+ </testsuites>
+ <filter>
+ <whitelist>
+ <directory suffix=".php">src</directory>
+ <exclude>
+ <file>src/functions.php</file>
+ </exclude>
+ </whitelist>
+ </filter>
+</phpunit>
diff --git a/www/wiki/vendor/guzzlehttp/streams/src/AppendStream.php b/www/wiki/vendor/guzzlehttp/streams/src/AppendStream.php
new file mode 100644
index 00000000..94bda717
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/AppendStream.php
@@ -0,0 +1,220 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+use GuzzleHttp\Stream\Exception\CannotAttachException;
+
+/**
+ * Reads from multiple streams, one after the other.
+ *
+ * This is a read-only stream decorator.
+ */
+class AppendStream implements StreamInterface
+{
+ /** @var StreamInterface[] Streams being decorated */
+ private $streams = [];
+
+ private $seekable = true;
+ private $current = 0;
+ private $pos = 0;
+ private $detached = false;
+
+ /**
+ * @param StreamInterface[] $streams Streams to decorate. Each stream must
+ * be readable.
+ */
+ public function __construct(array $streams = [])
+ {
+ foreach ($streams as $stream) {
+ $this->addStream($stream);
+ }
+ }
+
+ public function __toString()
+ {
+ try {
+ $this->seek(0);
+ 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 Utils::copyToString($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 attach($stream)
+ {
+ throw new CannotAttachException();
+ }
+
+ 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());
+ }
+
+ /**
+ * Attempts to seek to the given position. Only supports SEEK_SET.
+ *
+ * {@inheritdoc}
+ */
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ if (!$this->seekable || $whence !== SEEK_SET) {
+ return false;
+ }
+
+ $success = true;
+ $this->pos = $this->current = 0;
+
+ // Rewind each stream
+ foreach ($this->streams as $stream) {
+ if (!$stream->seek(0)) {
+ $success = false;
+ }
+ }
+
+ if (!$success) {
+ return false;
+ }
+
+ // Seek to the actual position by reading from each stream
+ while ($this->pos < $offset && !$this->eof()) {
+ $this->read(min(8096, $offset - $this->pos));
+ }
+
+ return $this->pos == $offset;
+ }
+
+ /**
+ * 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;
+
+ while ($remaining > 0) {
+ // Progress to the next stream if needed.
+ if ($this->streams[$this->current]->eof()) {
+ if ($this->current == $total) {
+ break;
+ }
+ $this->current++;
+ }
+ $buffer .= $this->streams[$this->current]->read($remaining);
+ $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)
+ {
+ return false;
+ }
+
+ public function getMetadata($key = null)
+ {
+ return $key ? null : [];
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/src/AsyncReadStream.php b/www/wiki/vendor/guzzlehttp/streams/src/AsyncReadStream.php
new file mode 100644
index 00000000..25ad9602
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/AsyncReadStream.php
@@ -0,0 +1,207 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * Represents an asynchronous read-only stream that supports a drain event and
+ * pumping data from a source stream.
+ *
+ * The AsyncReadStream can be used as a completely asynchronous stream, meaning
+ * the data you can read from the stream will immediately return only
+ * the data that is currently buffered.
+ *
+ * AsyncReadStream can also be used in a "blocking" manner if a "pump" function
+ * is provided. When a caller requests more bytes than are available in the
+ * buffer, then the pump function is used to block until the requested number
+ * of bytes are available or the remote source stream has errored, closed, or
+ * timed-out. This behavior isn't strictly "blocking" because the pump function
+ * can send other transfers while waiting on the desired buffer size to be
+ * ready for reading (e.g., continue to tick an event loop).
+ *
+ * @unstable This class is subject to change.
+ */
+class AsyncReadStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ /** @var callable|null Fn used to notify writers the buffer has drained */
+ private $drain;
+
+ /** @var callable|null Fn used to block for more data */
+ private $pump;
+
+ /** @var int|null Highwater mark of the underlying buffer */
+ private $hwm;
+
+ /** @var bool Whether or not drain needs to be called at some point */
+ private $needsDrain;
+
+ /** @var int The expected size of the remote source */
+ private $size;
+
+ /**
+ * In order to utilize high water marks to tell writers to slow down, the
+ * provided stream must answer to the "hwm" stream metadata variable,
+ * providing the high water mark. If no "hwm" metadata value is available,
+ * then the "drain" functionality is not utilized.
+ *
+ * This class accepts an associative array of configuration options.
+ *
+ * - drain: (callable) Function to invoke when the stream has drained,
+ * meaning the buffer is now writable again because the size of the
+ * buffer is at an acceptable level (e.g., below the high water mark).
+ * The function accepts a single argument, the buffer stream object that
+ * has drained.
+ * - pump: (callable) A function that accepts the number of bytes to read
+ * from the source stream. This function will block until all of the data
+ * that was requested has been read, EOF of the source stream, or the
+ * source stream is closed.
+ * - size: (int) The expected size in bytes of the data that will be read
+ * (if known up-front).
+ *
+ * @param StreamInterface $buffer Buffer that contains the data that has
+ * been read by the event loop.
+ * @param array $config Associative array of options.
+ *
+ * @throws \InvalidArgumentException if the buffer is not readable and
+ * writable.
+ */
+ public function __construct(
+ StreamInterface $buffer,
+ array $config = []
+ ) {
+ if (!$buffer->isReadable() || !$buffer->isWritable()) {
+ throw new \InvalidArgumentException(
+ 'Buffer must be readable and writable'
+ );
+ }
+
+ if (isset($config['size'])) {
+ $this->size = $config['size'];
+ }
+
+ static $callables = ['pump', 'drain'];
+ foreach ($callables as $check) {
+ if (isset($config[$check])) {
+ if (!is_callable($config[$check])) {
+ throw new \InvalidArgumentException(
+ $check . ' must be callable'
+ );
+ }
+ $this->{$check} = $config[$check];
+ }
+ }
+
+ $this->hwm = $buffer->getMetadata('hwm');
+
+ // Cannot drain when there's no high water mark.
+ if ($this->hwm === null) {
+ $this->drain = null;
+ }
+
+ $this->stream = $buffer;
+ }
+
+ /**
+ * Factory method used to create new async stream and an underlying buffer
+ * if no buffer is provided.
+ *
+ * This function accepts the same options as AsyncReadStream::__construct,
+ * but added the following key value pairs:
+ *
+ * - buffer: (StreamInterface) Buffer used to buffer data. If none is
+ * provided, a default buffer is created.
+ * - hwm: (int) High water mark to use if a buffer is created on your
+ * behalf.
+ * - max_buffer: (int) If provided, wraps the utilized buffer in a
+ * DroppingStream decorator to ensure that buffer does not exceed a given
+ * length. When exceeded, the stream will begin dropping data. Set the
+ * max_buffer to 0, to use a NullStream which does not store data.
+ * - write: (callable) A function that is invoked when data is written
+ * to the underlying buffer. The function accepts the buffer as the first
+ * argument, and the data being written as the second. The function MUST
+ * return the number of bytes that were written or false to let writers
+ * know to slow down.
+ * - drain: (callable) See constructor documentation.
+ * - pump: (callable) See constructor documentation.
+ *
+ * @param array $options Associative array of options.
+ *
+ * @return array Returns an array containing the buffer used to buffer
+ * data, followed by the ready to use AsyncReadStream object.
+ */
+ public static function create(array $options = [])
+ {
+ $maxBuffer = isset($options['max_buffer'])
+ ? $options['max_buffer']
+ : null;
+
+ if ($maxBuffer === 0) {
+ $buffer = new NullStream();
+ } elseif (isset($options['buffer'])) {
+ $buffer = $options['buffer'];
+ } else {
+ $hwm = isset($options['hwm']) ? $options['hwm'] : 16384;
+ $buffer = new BufferStream($hwm);
+ }
+
+ if ($maxBuffer > 0) {
+ $buffer = new DroppingStream($buffer, $options['max_buffer']);
+ }
+
+ // Call the on_write callback if an on_write function was provided.
+ if (isset($options['write'])) {
+ $onWrite = $options['write'];
+ $buffer = FnStream::decorate($buffer, [
+ 'write' => function ($string) use ($buffer, $onWrite) {
+ $result = $buffer->write($string);
+ $onWrite($buffer, $string);
+ return $result;
+ }
+ ]);
+ }
+
+ return [$buffer, new self($buffer, $options)];
+ }
+
+ public function getSize()
+ {
+ return $this->size;
+ }
+
+ public function isWritable()
+ {
+ return false;
+ }
+
+ public function write($string)
+ {
+ return false;
+ }
+
+ public function read($length)
+ {
+ if (!$this->needsDrain && $this->drain) {
+ $this->needsDrain = $this->stream->getSize() >= $this->hwm;
+ }
+
+ $result = $this->stream->read($length);
+
+ // If we need to drain, then drain when the buffer is empty.
+ if ($this->needsDrain && $this->stream->getSize() === 0) {
+ $this->needsDrain = false;
+ $drainFn = $this->drain;
+ $drainFn($this->stream);
+ }
+
+ $resultLen = strlen($result);
+
+ // If a pump was provided, the buffer is still open, and not enough
+ // data was given, then block until the data is provided.
+ if ($this->pump && $resultLen < $length) {
+ $pumpFn = $this->pump;
+ $result .= $pumpFn($length - $resultLen);
+ }
+
+ return $result;
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/src/BufferStream.php b/www/wiki/vendor/guzzlehttp/streams/src/BufferStream.php
new file mode 100644
index 00000000..0fffbd63
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/BufferStream.php
@@ -0,0 +1,138 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+use GuzzleHttp\Stream\Exception\CannotAttachException;
+
+/**
+ * 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.
+ *
+ * @package GuzzleHttp\Stream
+ */
+class BufferStream implements StreamInterface
+{
+ private $hwm;
+ private $buffer = '';
+
+ /**
+ * @param int $hwm High water mark, representing the preferred maximum
+ * buffer size. If the size of the buffer exceeds the high
+ * water mark, then calls to write will continue to succeed
+ * but will return false to inform writers to slow down
+ * until the buffer has been drained by reading from it.
+ */
+ public function __construct($hwm = 16384)
+ {
+ $this->hwm = $hwm;
+ }
+
+ public function __toString()
+ {
+ return $this->getContents();
+ }
+
+ public function getContents()
+ {
+ $buffer = $this->buffer;
+ $this->buffer = '';
+
+ return $buffer;
+ }
+
+ public function close()
+ {
+ $this->buffer = '';
+ }
+
+ public function detach()
+ {
+ $this->close();
+ }
+
+ public function attach($stream)
+ {
+ throw new CannotAttachException();
+ }
+
+ public function getSize()
+ {
+ return strlen($this->buffer);
+ }
+
+ public function isReadable()
+ {
+ return true;
+ }
+
+ public function isWritable()
+ {
+ return true;
+ }
+
+ public function isSeekable()
+ {
+ return false;
+ }
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ return false;
+ }
+
+ public function eof()
+ {
+ return strlen($this->buffer) === 0;
+ }
+
+ public function tell()
+ {
+ return false;
+ }
+
+ /**
+ * 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;
+
+ 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/www/wiki/vendor/guzzlehttp/streams/src/CachingStream.php b/www/wiki/vendor/guzzlehttp/streams/src/CachingStream.php
new file mode 100644
index 00000000..60bb9056
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/CachingStream.php
@@ -0,0 +1,122 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+use GuzzleHttp\Stream\Exception\SeekException;
+
+/**
+ * Stream decorator that can cache previously read bytes from a sequentially
+ * read stream.
+ */
+class CachingStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ /** @var StreamInterface Stream being wrapped */
+ private $remoteStream;
+
+ /** @var int Number of bytes to skip reading due to a write on the buffer */
+ private $skipReadBytes = 0;
+
+ /**
+ * We will treat the buffer object as the body of the stream
+ *
+ * @param StreamInterface $stream Stream to cache
+ * @param StreamInterface $target Optionally specify where data is cached
+ */
+ public function __construct(
+ StreamInterface $stream,
+ StreamInterface $target = null
+ ) {
+ $this->remoteStream = $stream;
+ $this->stream = $target ?: new Stream(fopen('php://temp', 'r+'));
+ }
+
+ public function getSize()
+ {
+ return max($this->stream->getSize(), $this->remoteStream->getSize());
+ }
+
+ /**
+ * {@inheritdoc}
+ * @throws SeekException When seeking with SEEK_END or when seeking
+ * past the total size of the buffer stream
+ */
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ if ($whence == SEEK_SET) {
+ $byte = $offset;
+ } elseif ($whence == SEEK_CUR) {
+ $byte = $offset + $this->tell();
+ } else {
+ return false;
+ }
+
+ // You cannot skip ahead past where you've read from the remote stream
+ if ($byte > $this->stream->getSize()) {
+ throw new SeekException(
+ $this,
+ $byte,
+ sprintf('Cannot seek to byte %d when the buffered stream only'
+ . ' contains %d bytes', $byte, $this->stream->getSize())
+ );
+ }
+
+ return $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();
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/src/DroppingStream.php b/www/wiki/vendor/guzzlehttp/streams/src/DroppingStream.php
new file mode 100644
index 00000000..56ee80c1
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/DroppingStream.php
@@ -0,0 +1,42 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * Stream decorator that begins dropping data once the size of the underlying
+ * stream becomes too full.
+ */
+class DroppingStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ private $maxLength;
+
+ /**
+ * @param StreamInterface $stream Underlying stream to decorate.
+ * @param int $maxLength Maximum size before dropping data.
+ */
+ public function __construct(StreamInterface $stream, $maxLength)
+ {
+ $this->stream = $stream;
+ $this->maxLength = $maxLength;
+ }
+
+ public function write($string)
+ {
+ $diff = $this->maxLength - $this->stream->getSize();
+
+ // Begin returning false when the underlying stream is too large.
+ if ($diff <= 0) {
+ return false;
+ }
+
+ // Write the stream or a subset of the stream if needed.
+ if (strlen($string) < $diff) {
+ return $this->stream->write($string);
+ }
+
+ $this->stream->write(substr($string, 0, $diff));
+
+ return false;
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/src/Exception/CannotAttachException.php b/www/wiki/vendor/guzzlehttp/streams/src/Exception/CannotAttachException.php
new file mode 100644
index 00000000..e631b9fa
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/Exception/CannotAttachException.php
@@ -0,0 +1,4 @@
+<?php
+namespace GuzzleHttp\Stream\Exception;
+
+class CannotAttachException extends \RuntimeException {}
diff --git a/www/wiki/vendor/guzzlehttp/streams/src/Exception/SeekException.php b/www/wiki/vendor/guzzlehttp/streams/src/Exception/SeekException.php
new file mode 100644
index 00000000..3f6d5eba
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/Exception/SeekException.php
@@ -0,0 +1,27 @@
+<?php
+namespace GuzzleHttp\Stream\Exception;
+
+use GuzzleHttp\Stream\StreamInterface;
+
+/**
+ * Exception thrown when a seek fails on a stream.
+ */
+class SeekException extends \RuntimeException
+{
+ private $stream;
+
+ public function __construct(StreamInterface $stream, $pos = 0, $msg = '')
+ {
+ $this->stream = $stream;
+ $msg = $msg ?: 'Could not seek the stream to position ' . $pos;
+ parent::__construct($msg);
+ }
+
+ /**
+ * @return StreamInterface
+ */
+ public function getStream()
+ {
+ return $this->stream;
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/src/FnStream.php b/www/wiki/vendor/guzzlehttp/streams/src/FnStream.php
new file mode 100644
index 00000000..6b5872d7
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/FnStream.php
@@ -0,0 +1,147 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * Compose stream implementations based on a hash of functions.
+ *
+ * Allows for easy testing and extension of a provided stream without needing
+ * to create a concrete class for a simple extension point.
+ */
+class FnStream implements StreamInterface
+{
+ /** @var array */
+ private $methods;
+
+ /** @var array Methods that must be implemented in the given array */
+ private static $slots = ['__toString', 'close', 'detach', 'attach',
+ 'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write',
+ 'isReadable', 'read', 'getContents', 'getMetadata'];
+
+ /**
+ * @param array $methods Hash of method name to a callable.
+ */
+ public function __construct(array $methods)
+ {
+ $this->methods = $methods;
+
+ // Create the functions on the class
+ foreach ($methods as $name => $fn) {
+ $this->{'_fn_' . $name} = $fn;
+ }
+ }
+
+ /**
+ * Lazily determine which methods are not implemented.
+ * @throws \BadMethodCallException
+ */
+ public function __get($name)
+ {
+ throw new \BadMethodCallException(str_replace('_fn_', '', $name)
+ . '() is not implemented in the FnStream');
+ }
+
+ /**
+ * The close method is called on the underlying stream only if possible.
+ */
+ public function __destruct()
+ {
+ if (isset($this->_fn_close)) {
+ call_user_func($this->_fn_close);
+ }
+ }
+
+ /**
+ * Adds custom functionality to an underlying stream by intercepting
+ * specific method calls.
+ *
+ * @param StreamInterface $stream Stream to decorate
+ * @param array $methods Hash of method name to a closure
+ *
+ * @return FnStream
+ */
+ public static function decorate(StreamInterface $stream, array $methods)
+ {
+ // If any of the required methods were not provided, then simply
+ // proxy to the decorated stream.
+ foreach (array_diff(self::$slots, array_keys($methods)) as $diff) {
+ $methods[$diff] = [$stream, $diff];
+ }
+
+ return new self($methods);
+ }
+
+ public function __toString()
+ {
+ return call_user_func($this->_fn___toString);
+ }
+
+ public function close()
+ {
+ return call_user_func($this->_fn_close);
+ }
+
+ public function detach()
+ {
+ return call_user_func($this->_fn_detach);
+ }
+
+ public function attach($stream)
+ {
+ return call_user_func($this->_fn_attach, $stream);
+ }
+
+ 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 seek($offset, $whence = SEEK_SET)
+ {
+ return 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/www/wiki/vendor/guzzlehttp/streams/src/GuzzleStreamWrapper.php b/www/wiki/vendor/guzzlehttp/streams/src/GuzzleStreamWrapper.php
new file mode 100644
index 00000000..4d049a69
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/GuzzleStreamWrapper.php
@@ -0,0 +1,117 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * Converts Guzzle streams into PHP stream resources.
+ */
+class GuzzleStreamWrapper
+{
+ /** @var resource */
+ public $context;
+
+ /** @var StreamInterface */
+ private $stream;
+
+ /** @var string r, r+, or w */
+ private $mode;
+
+ /**
+ * Returns a resource representing the stream.
+ *
+ * @param StreamInterface $stream The stream to get a resource for
+ *
+ * @return resource
+ * @throws \InvalidArgumentException if stream is not readable or writable
+ */
+ public static function getResource(StreamInterface $stream)
+ {
+ self::register();
+
+ if ($stream->isReadable()) {
+ $mode = $stream->isWritable() ? 'r+' : 'r';
+ } elseif ($stream->isWritable()) {
+ $mode = 'w';
+ } else {
+ throw new \InvalidArgumentException('The stream must be readable, '
+ . 'writable, or both.');
+ }
+
+ return fopen('guzzle://stream', $mode, null, stream_context_create([
+ 'guzzle' => ['stream' => $stream]
+ ]));
+ }
+
+ /**
+ * Registers the stream wrapper if needed
+ */
+ public static function register()
+ {
+ if (!in_array('guzzle', stream_get_wrappers())) {
+ stream_wrapper_register('guzzle', __CLASS__);
+ }
+ }
+
+ public function stream_open($path, $mode, $options, &$opened_path)
+ {
+ $options = stream_context_get_options($this->context);
+
+ if (!isset($options['guzzle']['stream'])) {
+ return false;
+ }
+
+ $this->mode = $mode;
+ $this->stream = $options['guzzle']['stream'];
+
+ return true;
+ }
+
+ public function stream_read($count)
+ {
+ return $this->stream->read($count);
+ }
+
+ public function stream_write($data)
+ {
+ return (int) $this->stream->write($data);
+ }
+
+ public function stream_tell()
+ {
+ return $this->stream->tell();
+ }
+
+ public function stream_eof()
+ {
+ return $this->stream->eof();
+ }
+
+ public function stream_seek($offset, $whence)
+ {
+ return $this->stream->seek($offset, $whence);
+ }
+
+ 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/www/wiki/vendor/guzzlehttp/streams/src/InflateStream.php b/www/wiki/vendor/guzzlehttp/streams/src/InflateStream.php
new file mode 100644
index 00000000..978af210
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/InflateStream.php
@@ -0,0 +1,27 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * Uses PHP's zlib.inflate filter to inflate deflate or gzipped content.
+ *
+ * This stream decorator skips the first 10 bytes of the given stream to remove
+ * the gzip header, converts the provided stream to a PHP stream resource,
+ * then appends the zlib.inflate filter. The stream is then converted back
+ * to a Guzzle stream resource to be used as a Guzzle stream.
+ *
+ * @link http://tools.ietf.org/html/rfc1952
+ * @link http://php.net/manual/en/filters.compression.php
+ */
+class InflateStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ public function __construct(StreamInterface $stream)
+ {
+ // Skip the first 10 bytes
+ $stream = new LimitStream($stream, -1, 10);
+ $resource = GuzzleStreamWrapper::getResource($stream);
+ stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ);
+ $this->stream = new Stream($resource);
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/src/LazyOpenStream.php b/www/wiki/vendor/guzzlehttp/streams/src/LazyOpenStream.php
new file mode 100644
index 00000000..6242ee7b
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/LazyOpenStream.php
@@ -0,0 +1,37 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * Lazily reads or writes to a file that is opened only after an IO operation
+ * take place on the stream.
+ */
+class LazyOpenStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ /** @var string File to open */
+ private $filename;
+
+ /** @var string $mode */
+ private $mode;
+
+ /**
+ * @param string $filename File to lazily open
+ * @param string $mode fopen mode to use when opening the stream
+ */
+ public function __construct($filename, $mode)
+ {
+ $this->filename = $filename;
+ $this->mode = $mode;
+ }
+
+ /**
+ * Creates the underlying stream lazily when required.
+ *
+ * @return StreamInterface
+ */
+ protected function createStream()
+ {
+ return Stream::factory(Utils::open($this->filename, $this->mode));
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/src/LimitStream.php b/www/wiki/vendor/guzzlehttp/streams/src/LimitStream.php
new file mode 100644
index 00000000..e9fad985
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/LimitStream.php
@@ -0,0 +1,161 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+use GuzzleHttp\Stream\Exception\SeekException;
+
+/**
+ * Decorator used to return only a subset of a stream
+ */
+class LimitStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ /** @var int Offset to start reading from */
+ private $offset;
+
+ /** @var int Limit the number of bytes that can be read */
+ private $limit;
+
+ /**
+ * @param StreamInterface $stream Stream to wrap
+ * @param int $limit Total number of bytes to allow to be read
+ * from the stream. Pass -1 for no limit.
+ * @param int|null $offset Position to seek to before reading (only
+ * works on seekable streams).
+ */
+ public function __construct(
+ StreamInterface $stream,
+ $limit = -1,
+ $offset = 0
+ ) {
+ $this->stream = $stream;
+ $this->setLimit($limit);
+ $this->setOffset($offset);
+ }
+
+ public function eof()
+ {
+ // Always return true if the underlying stream is EOF
+ if ($this->stream->eof()) {
+ return true;
+ }
+
+ // No limit and the underlying stream is not at EOF
+ if ($this->limit == -1) {
+ return false;
+ }
+
+ $tell = $this->stream->tell();
+ if ($tell === false) {
+ return false;
+ }
+
+ return $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) {
+ return false;
+ }
+
+ $offset += $this->offset;
+
+ if ($this->limit !== -1) {
+ if ($offset > $this->offset + $this->limit) {
+ $offset = $this->offset + $this->limit;
+ }
+ }
+
+ return $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
+ *
+ * @return self
+ * @throws SeekException
+ */
+ 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->seek($offset)) {
+ if ($current > $offset) {
+ throw new SeekException($this, $offset);
+ } else {
+ $this->stream->read($offset - $current);
+ }
+ }
+ }
+
+ $this->offset = $offset;
+
+ return $this;
+ }
+
+ /**
+ * 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.
+ * @return self
+ */
+ public function setLimit($limit)
+ {
+ $this->limit = $limit;
+
+ return $this;
+ }
+
+ 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));
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/src/MetadataStreamInterface.php b/www/wiki/vendor/guzzlehttp/streams/src/MetadataStreamInterface.php
new file mode 100644
index 00000000..c1433ad8
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/MetadataStreamInterface.php
@@ -0,0 +1,11 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * This interface is deprecated and should no longer be used. Just use
+ * StreamInterface now that the getMetadata method has been added to
+ * StreamInterface.
+ *
+ * @deprecated
+ */
+interface MetadataStreamInterface extends StreamInterface {}
diff --git a/www/wiki/vendor/guzzlehttp/streams/src/NoSeekStream.php b/www/wiki/vendor/guzzlehttp/streams/src/NoSeekStream.php
new file mode 100644
index 00000000..3d42395d
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/NoSeekStream.php
@@ -0,0 +1,25 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * Stream decorator that prevents a stream from being seeked
+ */
+class NoSeekStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ return false;
+ }
+
+ public function isSeekable()
+ {
+ return false;
+ }
+
+ public function attach($stream)
+ {
+ $this->stream->attach($stream);
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/src/NullStream.php b/www/wiki/vendor/guzzlehttp/streams/src/NullStream.php
new file mode 100644
index 00000000..41ee7766
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/NullStream.php
@@ -0,0 +1,78 @@
+<?php
+namespace GuzzleHttp\Stream;
+use GuzzleHttp\Stream\Exception\CannotAttachException;
+
+/**
+ * Does not store any data written to it.
+ */
+class NullStream implements StreamInterface
+{
+ public function __toString()
+ {
+ return '';
+ }
+
+ public function getContents()
+ {
+ return '';
+ }
+
+ public function close() {}
+
+ public function detach() {}
+
+ public function attach($stream)
+ {
+ throw new CannotAttachException();
+ }
+
+ public function getSize()
+ {
+ return 0;
+ }
+
+ public function isReadable()
+ {
+ return true;
+ }
+
+ public function isWritable()
+ {
+ return true;
+ }
+
+ public function isSeekable()
+ {
+ return true;
+ }
+
+ public function eof()
+ {
+ return true;
+ }
+
+ public function tell()
+ {
+ return 0;
+ }
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ return false;
+ }
+
+ public function read($length)
+ {
+ return false;
+ }
+
+ public function write($string)
+ {
+ return strlen($string);
+ }
+
+ public function getMetadata($key = null)
+ {
+ return $key ? null : [];
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/src/PumpStream.php b/www/wiki/vendor/guzzlehttp/streams/src/PumpStream.php
new file mode 100644
index 00000000..99632072
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/PumpStream.php
@@ -0,0 +1,161 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+use GuzzleHttp\Stream\Exception\CannotAttachException;
+
+/**
+ * Provides a read only stream that pumps data from a PHP callable.
+ *
+ * When invoking the provided callable, the PumpStream will pass the amount of
+ * data requested to read to the callable. The callable can choose to ignore
+ * this value and return fewer or more bytes than requested. Any extra data
+ * returned by the provided callable is buffered internally until drained using
+ * the read() function of the PumpStream. The provided callable MUST return
+ * false when there is no more data to read.
+ */
+class PumpStream implements StreamInterface
+{
+ /** @var callable */
+ private $source;
+
+ /** @var int */
+ private $size;
+
+ /** @var int */
+ private $tellPos = 0;
+
+ /** @var array */
+ private $metadata;
+
+ /** @var BufferStream */
+ private $buffer;
+
+ /**
+ * @param callable $source Source of the stream data. The callable MAY
+ * accept an integer argument used to control the
+ * amount of data to return. The callable MUST
+ * return a string when called, or false on error
+ * or EOF.
+ * @param array $options Stream options:
+ * - metadata: Hash of metadata to use with stream.
+ * - size: Size of the stream, if known.
+ */
+ public function __construct(callable $source, array $options = [])
+ {
+ $this->source = $source;
+ $this->size = isset($options['size']) ? $options['size'] : null;
+ $this->metadata = isset($options['metadata']) ? $options['metadata'] : [];
+ $this->buffer = new BufferStream();
+ }
+
+ public function __toString()
+ {
+ return Utils::copyToString($this);
+ }
+
+ public function close()
+ {
+ $this->detach();
+ }
+
+ public function detach()
+ {
+ $this->tellPos = false;
+ $this->source = null;
+ }
+
+ public function attach($stream)
+ {
+ throw new CannotAttachException();
+ }
+
+ 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 seek($offset, $whence = SEEK_SET)
+ {
+ return false;
+ }
+
+ public function isWritable()
+ {
+ return false;
+ }
+
+ public function write($string)
+ {
+ return false;
+ }
+
+ 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/www/wiki/vendor/guzzlehttp/streams/src/Stream.php b/www/wiki/vendor/guzzlehttp/streams/src/Stream.php
new file mode 100644
index 00000000..7adbc5e3
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/Stream.php
@@ -0,0 +1,261 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * PHP stream implementation
+ */
+class Stream implements StreamInterface
+{
+ private $stream;
+ private $size;
+ private $seekable;
+ private $readable;
+ private $writable;
+ private $uri;
+ private $customMetadata;
+
+ /** @var array Hash of readable and writable stream types */
+ private static $readWriteHash = [
+ 'read' => [
+ 'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true,
+ 'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true,
+ 'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true,
+ 'x+t' => true, 'c+t' => true, 'a+' => true
+ ],
+ 'write' => [
+ 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true,
+ 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true,
+ 'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true,
+ 'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true
+ ]
+ ];
+
+ /**
+ * Create a new stream based on the input type.
+ *
+ * This factory accepts the same associative array of options as described
+ * in the constructor.
+ *
+ * @param resource|string|StreamInterface $resource Entity body data
+ * @param array $options Additional options
+ *
+ * @return Stream
+ * @throws \InvalidArgumentException if the $resource arg is not valid.
+ */
+ public static function factory($resource = '', array $options = [])
+ {
+ $type = gettype($resource);
+
+ if ($type == 'string') {
+ $stream = fopen('php://temp', 'r+');
+ if ($resource !== '') {
+ fwrite($stream, $resource);
+ fseek($stream, 0);
+ }
+ return new self($stream, $options);
+ }
+
+ if ($type == 'resource') {
+ return new self($resource, $options);
+ }
+
+ if ($resource instanceof StreamInterface) {
+ return $resource;
+ }
+
+ if ($type == 'object' && method_exists($resource, '__toString')) {
+ return self::factory((string) $resource, $options);
+ }
+
+ if (is_callable($resource)) {
+ return new PumpStream($resource, $options);
+ }
+
+ if ($resource instanceof \Iterator) {
+ return new PumpStream(function () use ($resource) {
+ if (!$resource->valid()) {
+ return false;
+ }
+ $result = $resource->current();
+ $resource->next();
+ return $result;
+ }, $options);
+ }
+
+ throw new \InvalidArgumentException('Invalid resource type: ' . $type);
+ }
+
+ /**
+ * 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->attach($stream);
+ }
+
+ /**
+ * Closes the stream when the destructed
+ */
+ public function __destruct()
+ {
+ $this->close();
+ }
+
+ public function __toString()
+ {
+ if (!$this->stream) {
+ return '';
+ }
+
+ $this->seek(0);
+
+ return (string) stream_get_contents($this->stream);
+ }
+
+ public function getContents()
+ {
+ return $this->stream ? stream_get_contents($this->stream) : '';
+ }
+
+ public function close()
+ {
+ if (is_resource($this->stream)) {
+ fclose($this->stream);
+ }
+
+ $this->detach();
+ }
+
+ public function detach()
+ {
+ $result = $this->stream;
+ $this->stream = $this->size = $this->uri = null;
+ $this->readable = $this->writable = $this->seekable = false;
+
+ return $result;
+ }
+
+ public function attach($stream)
+ {
+ $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 getSize()
+ {
+ if ($this->size !== null) {
+ return $this->size;
+ }
+
+ if (!$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()
+ {
+ return $this->stream ? ftell($this->stream) : false;
+ }
+
+ public function setSize($size)
+ {
+ $this->size = $size;
+
+ return $this;
+ }
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ return $this->seekable
+ ? fseek($this->stream, $offset, $whence) === 0
+ : false;
+ }
+
+ public function read($length)
+ {
+ return $this->readable ? fread($this->stream, $length) : false;
+ }
+
+ public function write($string)
+ {
+ // We can't know the size after writing anything
+ $this->size = null;
+
+ return $this->writable ? fwrite($this->stream, $string) : false;
+ }
+
+ public function getMetadata($key = null)
+ {
+ if (!$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/www/wiki/vendor/guzzlehttp/streams/src/StreamDecoratorTrait.php b/www/wiki/vendor/guzzlehttp/streams/src/StreamDecoratorTrait.php
new file mode 100644
index 00000000..39c19c58
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/StreamDecoratorTrait.php
@@ -0,0 +1,143 @@
+<?php
+namespace GuzzleHttp\Stream;
+use GuzzleHttp\Stream\Exception\CannotAttachException;
+
+/**
+ * Stream decorator trait
+ * @property StreamInterface stream
+ */
+trait StreamDecoratorTrait
+{
+ /**
+ * @param StreamInterface $stream Stream to decorate
+ */
+ public function __construct(StreamInterface $stream)
+ {
+ $this->stream = $stream;
+ }
+
+ /**
+ * Magic method used to create a new stream if streams are not added in
+ * the constructor of a decorator (e.g., LazyOpenStream).
+ */
+ 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 {
+ $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 Utils::copyToString($this);
+ }
+
+ /**
+ * Allow decorators to implement custom methods
+ *
+ * @param string $method Missing method name
+ * @param array $args Method arguments
+ *
+ * @return mixed
+ */
+ public function __call($method, array $args)
+ {
+ $result = call_user_func_array(array($this->stream, $method), $args);
+
+ // Always return the wrapped object if the result is a return $this
+ return $result === $this->stream ? $this : $result;
+ }
+
+ public function close()
+ {
+ $this->stream->close();
+ }
+
+ public function getMetadata($key = null)
+ {
+ return $this->stream->getMetadata($key);
+ }
+
+ public function detach()
+ {
+ return $this->stream->detach();
+ }
+
+ public function attach($stream)
+ {
+ throw new CannotAttachException();
+ }
+
+ 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 seek($offset, $whence = SEEK_SET)
+ {
+ return $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('createStream() not implemented in '
+ . get_class($this));
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/src/StreamInterface.php b/www/wiki/vendor/guzzlehttp/streams/src/StreamInterface.php
new file mode 100644
index 00000000..fd19c6f2
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/StreamInterface.php
@@ -0,0 +1,159 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+/**
+ * Describes a stream instance.
+ */
+interface StreamInterface
+{
+ /**
+ * Attempts to seek to the beginning of the stream and reads all data into
+ * a string until the end of the stream is reached.
+ *
+ * Warning: This could attempt to load a large amount of data into memory.
+ *
+ * @return string
+ */
+ public function __toString();
+
+ /**
+ * Closes the stream and any underlying resources.
+ */
+ public function close();
+
+ /**
+ * Separates any underlying resources from the stream.
+ *
+ * After the underlying resource has been detached, the stream object is in
+ * an unusable state. If you wish to use a Stream object as a PHP stream
+ * but keep the Stream object in a consistent state, use
+ * {@see GuzzleHttp\Stream\GuzzleStreamWrapper::getResource}.
+ *
+ * @return resource|null Returns the underlying PHP stream resource or null
+ * if the Stream object did not utilize an underlying
+ * stream resource.
+ */
+ public function detach();
+
+ /**
+ * Replaces the underlying stream resource with the provided stream.
+ *
+ * Use this method to replace the underlying stream with another; as an
+ * example, in server-side code, if you decide to return a file, you
+ * would replace the original content-oriented stream with the file
+ * stream.
+ *
+ * Any internal state such as caching of cursor position should be reset
+ * when attach() is called, as the stream has changed.
+ *
+ * @param resource $stream
+ *
+ * @return void
+ */
+ public function attach($stream);
+
+ /**
+ * Get the size of the stream if known
+ *
+ * @return int|null Returns the size in bytes if known, or null if unknown
+ */
+ public function getSize();
+
+ /**
+ * Returns the current position of the file read/write pointer
+ *
+ * @return int|bool Returns the position of the file pointer or false on error
+ */
+ public function tell();
+
+ /**
+ * Returns true if the stream is at the end of the stream.
+ *
+ * @return bool
+ */
+ public function eof();
+
+ /**
+ * Returns whether or not the stream is seekable
+ *
+ * @return bool
+ */
+ public function isSeekable();
+
+ /**
+ * Seek to a position in the stream
+ *
+ * @param int $offset Stream offset
+ * @param int $whence Specifies how the cursor position will be calculated
+ * based on the seek offset. Valid values are identical
+ * to the built-in PHP $whence values for `fseek()`.
+ * SEEK_SET: Set position equal to offset bytes
+ * SEEK_CUR: Set position to current location plus offset
+ * SEEK_END: Set position to end-of-stream plus offset
+ *
+ * @return bool Returns true on success or false on failure
+ * @link http://www.php.net/manual/en/function.fseek.php
+ */
+ public function seek($offset, $whence = SEEK_SET);
+
+ /**
+ * Returns whether or not the stream is writable
+ *
+ * @return bool
+ */
+ public function isWritable();
+
+ /**
+ * Write data to the stream
+ *
+ * @param string $string The string that is to be written.
+ *
+ * @return int|bool Returns the number of bytes written to the stream on
+ * success returns false on failure (e.g., broken pipe,
+ * writer needs to slow down, buffer is full, etc.)
+ */
+ public function write($string);
+
+ /**
+ * Returns whether or not the stream is readable
+ *
+ * @return bool
+ */
+ public function isReadable();
+
+ /**
+ * Read data from the stream
+ *
+ * @param int $length Read up to $length bytes from the object and return
+ * them. Fewer than $length bytes may be returned if
+ * underlying stream call returns fewer bytes.
+ *
+ * @return string Returns the data read from the stream.
+ */
+ public function read($length);
+
+ /**
+ * Returns the remaining contents of the stream as a string.
+ *
+ * Note: this could potentially load a large amount of data into memory.
+ *
+ * @return string
+ */
+ public function getContents();
+
+ /**
+ * Get stream metadata as an associative array or retrieve a specific key.
+ *
+ * The keys returned are identical to the keys returned from PHP's
+ * stream_get_meta_data() function.
+ *
+ * @param string $key Specific metadata to retrieve.
+ *
+ * @return array|mixed|null Returns an associative array if no key is
+ * no key is provided. Returns a specific key
+ * value if a key is provided and the value is
+ * found, or null if the key is not found.
+ * @see http://php.net/manual/en/function.stream-get-meta-data.php
+ */
+ public function getMetadata($key = null);
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/src/Utils.php b/www/wiki/vendor/guzzlehttp/streams/src/Utils.php
new file mode 100644
index 00000000..94cb42d3
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/src/Utils.php
@@ -0,0 +1,196 @@
+<?php
+namespace GuzzleHttp\Stream;
+
+use GuzzleHttp\Stream\Exception\SeekException;
+
+/**
+ * Static utility class because PHP's autoloaders don't support the concept
+ * of namespaced function autoloading.
+ */
+class Utils
+{
+ /**
+ * 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
+ */
+ public static function open($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
+ */
+ public static function copyToString(StreamInterface $stream, $maxLen = -1)
+ {
+ $buffer = '';
+
+ if ($maxLen === -1) {
+ while (!$stream->eof()) {
+ $buf = $stream->read(1048576);
+ if ($buf === false) {
+ break;
+ }
+ $buffer .= $buf;
+ }
+ return $buffer;
+ }
+
+ $len = 0;
+ while (!$stream->eof() && $len < $maxLen) {
+ $buf = $stream->read($maxLen - $len);
+ if ($buf === false) {
+ 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.
+ */
+ public static function copyToStream(
+ 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 SeekException
+ */
+ public static function hash(
+ StreamInterface $stream,
+ $algo,
+ $rawOutput = false
+ ) {
+ $pos = $stream->tell();
+
+ if ($pos > 0 && !$stream->seek(0)) {
+ throw new SeekException($stream);
+ }
+
+ $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
+ */
+ public static function readline(StreamInterface $stream, $maxLength = null)
+ {
+ $buffer = '';
+ $size = 0;
+
+ while (!$stream->eof()) {
+ if (false === ($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;
+ }
+
+ /**
+ * Alias of GuzzleHttp\Stream\Stream::factory.
+ *
+ * @param mixed $resource Resource to create
+ * @param array $options Associative array of stream options defined in
+ * {@see \GuzzleHttp\Stream\Stream::__construct}
+ *
+ * @return StreamInterface
+ *
+ * @see GuzzleHttp\Stream\Stream::factory
+ * @see GuzzleHttp\Stream\Stream::__construct
+ */
+ public static function create($resource, array $options = [])
+ {
+ return Stream::factory($resource, $options);
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/tests/AppendStreamTest.php b/www/wiki/vendor/guzzlehttp/streams/tests/AppendStreamTest.php
new file mode 100644
index 00000000..78798d9f
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/tests/AppendStreamTest.php
@@ -0,0 +1,178 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\AppendStream;
+use GuzzleHttp\Stream\Stream;
+
+class AppendStreamTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Each stream must be readable
+ */
+ public function testValidatesStreamsAreReadable()
+ {
+ $a = new AppendStream();
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\StreamInterface')
+ ->setMethods(['isReadable'])
+ ->getMockForAbstractClass();
+ $s->expects($this->once())
+ ->method('isReadable')
+ ->will($this->returnValue(false));
+ $a->addStream($s);
+ }
+
+ public function testValidatesSeekType()
+ {
+ $a = new AppendStream();
+ $this->assertFalse($a->seek(100, SEEK_CUR));
+ }
+
+ public function testTriesToRewindOnSeek()
+ {
+ $a = new AppendStream();
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\StreamInterface')
+ ->setMethods(['isReadable', 'seek', '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('seek')
+ ->will($this->returnValue(false));
+ $a->addStream($s);
+ $this->assertFalse($a->seek(10));
+ }
+
+ public function testSeeksToPositionByReading()
+ {
+ $a = new AppendStream([
+ Stream::factory('foo'),
+ Stream::factory('bar'),
+ Stream::factory('baz'),
+ ]);
+
+ $this->assertTrue($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 = Stream::factory('foo');
+ $s2 = Stream::factory('foo');
+ $a = new AppendStream([$s1, $s2]);
+ $this->assertSame('foofoo', (string) $a);
+ $a->detach();
+ $this->assertSame('', (string) $a);
+ $this->assertSame(0, $a->getSize());
+ }
+
+ public function testClosesEachStream()
+ {
+ $s1 = Stream::factory('foo');
+ $a = new AppendStream([$s1]);
+ $a->close();
+ $this->assertSame('', (string) $a);
+ }
+
+ public function testIsNotWritable()
+ {
+ $a = new AppendStream([Stream::factory('foo')]);
+ $this->assertFalse($a->isWritable());
+ $this->assertTrue($a->isSeekable());
+ $this->assertTrue($a->isReadable());
+ $this->assertFalse($a->write('foo'));
+ }
+
+ public function testDoesNotNeedStreams()
+ {
+ $a = new AppendStream();
+ $this->assertEquals('', (string) $a);
+ }
+
+ public function testCanReadFromMultipleStreams()
+ {
+ $a = new AppendStream([
+ Stream::factory('foo'),
+ Stream::factory('bar'),
+ Stream::factory('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->assertTrue($a->eof());
+ $this->assertSame(9, $a->tell());
+ $this->assertEquals('foobarbaz', (string) $a);
+ }
+
+ public function testCanDetermineSizeFromMultipleStreams()
+ {
+ $a = new AppendStream([
+ Stream::factory('foo'),
+ Stream::factory('bar')
+ ]);
+ $this->assertEquals(6, $a->getSize());
+
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\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('GuzzleHttp\Stream\StreamInterface')
+ ->setMethods(['read', 'isReadable', 'eof'])
+ ->getMockForAbstractClass();
+ $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'));
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Stream\Exception\CannotAttachException
+ */
+ public function testCannotAttach()
+ {
+ $p = new AppendStream();
+ $p->attach('a');
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/tests/AsyncReadStreamTest.php b/www/wiki/vendor/guzzlehttp/streams/tests/AsyncReadStreamTest.php
new file mode 100644
index 00000000..8c789959
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/tests/AsyncReadStreamTest.php
@@ -0,0 +1,186 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\AsyncReadStream;
+use GuzzleHttp\Stream\BufferStream;
+use GuzzleHttp\Stream\FnStream;
+use GuzzleHttp\Stream\Stream;
+
+class AsyncReadStreamTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Buffer must be readable and writable
+ */
+ public function testValidatesReadableBuffer()
+ {
+ new AsyncReadStream(FnStream::decorate(
+ Stream::factory(),
+ ['isReadable' => function () { return false; }]
+ ));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Buffer must be readable and writable
+ */
+ public function testValidatesWritableBuffer()
+ {
+ new AsyncReadStream(FnStream::decorate(
+ Stream::factory(),
+ ['isWritable' => function () { return false; }]
+ ));
+ }
+
+ public function testValidatesHwmMetadata()
+ {
+ $a = new AsyncReadStream(Stream::factory(), [
+ 'drain' => function() {}
+ ]);
+ $this->assertNull($this->readAttribute($a, 'drain'));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage pump must be callable
+ */
+ public function testValidatesPumpIsCallable()
+ {
+ new AsyncReadStream(new BufferStream(), ['pump' => true]);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage drain must be callable
+ */
+ public function testValidatesDrainIsCallable()
+ {
+ new AsyncReadStream(new BufferStream(), ['drain' => true]);
+ }
+
+ public function testCanInitialize()
+ {
+ $buffer = new BufferStream();
+ $a = new AsyncReadStream($buffer, [
+ 'size' => 10,
+ 'drain' => function () {},
+ 'pump' => function () {},
+ ]);
+ $this->assertSame($buffer, $this->readAttribute($a, 'stream'));
+ $this->assertTrue(is_callable($this->readAttribute($a, 'drain')));
+ $this->assertTrue(is_callable($this->readAttribute($a, 'pump')));
+ $this->assertTrue($a->isReadable());
+ $this->assertFalse($a->isSeekable());
+ $this->assertFalse($a->isWritable());
+ $this->assertFalse($a->write('foo'));
+ $this->assertEquals(10, $a->getSize());
+ }
+
+ public function testReadsFromBufferWithNoDrainOrPump()
+ {
+ $buffer = new BufferStream();
+ $a = new AsyncReadStream($buffer);
+ $buffer->write('foo');
+ $this->assertNull($a->getSize());
+ $this->assertEquals('foo', $a->read(10));
+ $this->assertEquals('', $a->read(10));
+ }
+
+ public function testCallsPumpForMoreDataWhenRequested()
+ {
+ $called = 0;
+ $buffer = new BufferStream();
+ $a = new AsyncReadStream($buffer, [
+ 'pump' => function ($size) use (&$called) {
+ $called++;
+ return str_repeat('.', $size);
+ }
+ ]);
+ $buffer->write('foobar');
+ $this->assertEquals('foo', $a->read(3));
+ $this->assertEquals(0, $called);
+ $this->assertEquals('bar.....', $a->read(8));
+ $this->assertEquals(1, $called);
+ $this->assertEquals('..', $a->read(2));
+ $this->assertEquals(2, $called);
+ }
+
+ public function testCallsDrainWhenNeeded()
+ {
+ $called = 0;
+ $buffer = new BufferStream(5);
+ $a = new AsyncReadStream($buffer, [
+ 'drain' => function (BufferStream $b) use (&$called, $buffer) {
+ $this->assertSame($b, $buffer);
+ $called++;
+ }
+ ]);
+
+ $buffer->write('foobar');
+ $this->assertEquals(6, $buffer->getSize());
+ $this->assertEquals(0, $called);
+
+ $a->read(3);
+ $this->assertTrue($this->readAttribute($a, 'needsDrain'));
+ $this->assertEquals(3, $buffer->getSize());
+ $this->assertEquals(0, $called);
+
+ $a->read(3);
+ $this->assertEquals(0, $buffer->getSize());
+ $this->assertFalse($this->readAttribute($a, 'needsDrain'));
+ $this->assertEquals(1, $called);
+ }
+
+ public function testCreatesBufferWithNoConfig()
+ {
+ list($buffer, $async) = AsyncReadStream::create();
+ $this->assertInstanceOf('GuzzleHttp\Stream\BufferStream', $buffer);
+ $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
+ }
+
+ public function testCreatesBufferWithSpecifiedBuffer()
+ {
+ $buf = new BufferStream();
+ list($buffer, $async) = AsyncReadStream::create(['buffer' => $buf]);
+ $this->assertSame($buf, $buffer);
+ $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
+ }
+
+ public function testCreatesNullStream()
+ {
+ list($buffer, $async) = AsyncReadStream::create(['max_buffer' => 0]);
+ $this->assertInstanceOf('GuzzleHttp\Stream\NullStream', $buffer);
+ $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
+ }
+
+ public function testCreatesDroppingStream()
+ {
+ list($buffer, $async) = AsyncReadStream::create(['max_buffer' => 5]);
+ $this->assertInstanceOf('GuzzleHttp\Stream\DroppingStream', $buffer);
+ $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
+ $buffer->write('12345678910');
+ $this->assertEquals(5, $buffer->getSize());
+ }
+
+ public function testCreatesOnWriteStream()
+ {
+ $c = 0;
+ $b = new BufferStream();
+ list($buffer, $async) = AsyncReadStream::create([
+ 'buffer' => $b,
+ 'write' => function (BufferStream $buf, $data) use (&$c, $b) {
+ $this->assertSame($buf, $b);
+ $this->assertEquals('foo', $data);
+ $c++;
+ }
+ ]);
+ $this->assertInstanceOf('GuzzleHttp\Stream\FnStream', $buffer);
+ $this->assertInstanceOf('GuzzleHttp\Stream\AsyncReadStream', $async);
+ $this->assertEquals(0, $c);
+ $this->assertEquals(3, $buffer->write('foo'));
+ $this->assertEquals(1, $c);
+ $this->assertEquals(3, $buffer->write('foo'));
+ $this->assertEquals(2, $c);
+ $this->assertEquals('foofoo', (string) $buffer);
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/tests/BufferStreamTest.php b/www/wiki/vendor/guzzlehttp/streams/tests/BufferStreamTest.php
new file mode 100644
index 00000000..f9bfea21
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/tests/BufferStreamTest.php
@@ -0,0 +1,69 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\BufferStream;
+
+class BufferStreamTest extends \PHPUnit_Framework_TestCase
+{
+ public function testHasMetadata()
+ {
+ $b = new BufferStream(10);
+ $this->assertTrue($b->isReadable());
+ $this->assertTrue($b->isWritable());
+ $this->assertFalse($b->isSeekable());
+ $this->assertEquals(null, $b->getMetadata('foo'));
+ $this->assertEquals(10, $b->getMetadata('hwm'));
+ $this->assertEquals([], $b->getMetadata());
+ }
+
+ public function testRemovesReadDataFromBuffer()
+ {
+ $b = new BufferStream();
+ $this->assertEquals(3, $b->write('foo'));
+ $this->assertEquals(3, $b->getSize());
+ $this->assertFalse($b->eof());
+ $this->assertEquals('foo', $b->read(10));
+ $this->assertTrue($b->eof());
+ $this->assertEquals('', $b->read(10));
+ }
+
+ 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);
+ $this->assertFalse($b->tell());
+ }
+
+ public function testDetachClearsBuffer()
+ {
+ $b = new BufferStream();
+ $b->write('foo');
+ $b->detach();
+ $this->assertEquals(0, $b->tell());
+ $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'));
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Stream\Exception\CannotAttachException
+ */
+ public function testCannotAttach()
+ {
+ $p = new BufferStream();
+ $p->attach('a');
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/tests/CachingStreamTest.php b/www/wiki/vendor/guzzlehttp/streams/tests/CachingStreamTest.php
new file mode 100644
index 00000000..ea969b3a
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/tests/CachingStreamTest.php
@@ -0,0 +1,136 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\Stream;
+use GuzzleHttp\Stream\CachingStream;
+use GuzzleHttp\Stream\Utils;
+
+/**
+ * @covers GuzzleHttp\Stream\CachingStream
+ */
+class CachingStreamTest extends \PHPUnit_Framework_TestCase
+{
+ /** @var CachingStream */
+ protected $body;
+
+ /** @var Stream */
+ protected $decorated;
+
+ public function setUp()
+ {
+ $this->decorated = Stream::factory('testing');
+ $this->body = new CachingStream($this->decorated);
+ }
+
+ public function tearDown()
+ {
+ $this->decorated->close();
+ $this->body->close();
+ }
+
+ public function testUsesRemoteSizeIfPossible()
+ {
+ $body = Stream::factory('test');
+ $caching = new CachingStream($body);
+ $this->assertEquals(4, $caching->getSize());
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Cannot seek to byte 10
+ */
+ public function testCannotSeekPastWhatHasBeenRead()
+ {
+ $this->body->seek(10);
+ }
+
+ public function testCannotUseSeekEnd()
+ {
+ $this->assertFalse($this->body->seek(2, SEEK_END));
+ }
+
+ public function testRewindUsesSeek()
+ {
+ $a = Stream::factory('foo');
+ $d = $this->getMockBuilder('GuzzleHttp\Stream\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 = Stream::factory(
+ 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", Utils::readline($body));
+ $this->assertEquals("0001\n", Utils::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", Utils::readline($body));
+ $this->assertEquals(0, $this->readAttribute($body, 'skipReadBytes'));
+ $this->assertEquals("0004\n", Utils::readline($body));
+ $this->assertEquals("0005\n", Utils::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", Utils::readline($body));
+ $this->assertEquals("0003\n", Utils::readline($body));
+ $this->assertEquals("0004\n", Utils::readline($body));
+ $this->assertEquals("0005\n", Utils::readline($body));
+ $this->assertEquals("0006\n", Utils::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 = Stream::factory($s);
+ $d = new CachingStream($a);
+ $d->close();
+ $this->assertFalse(is_resource($s));
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/tests/DroppingStreamTest.php b/www/wiki/vendor/guzzlehttp/streams/tests/DroppingStreamTest.php
new file mode 100644
index 00000000..bb2cb220
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/tests/DroppingStreamTest.php
@@ -0,0 +1,26 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\BufferStream;
+use GuzzleHttp\Stream\DroppingStream;
+
+class DroppingStreamTest extends \PHPUnit_Framework_TestCase
+{
+ public function testBeginsDroppingWhenSizeExceeded()
+ {
+ $stream = new BufferStream();
+ $drop = new DroppingStream($stream, 5);
+ $this->assertEquals(3, $drop->write('hel'));
+ $this->assertFalse($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->assertFalse($drop->write('test'));
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/tests/Exception/SeekExceptionTest.php b/www/wiki/vendor/guzzlehttp/streams/tests/Exception/SeekExceptionTest.php
new file mode 100644
index 00000000..fd8cd1ad
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/tests/Exception/SeekExceptionTest.php
@@ -0,0 +1,16 @@
+<?php
+namespace GuzzleHttp\Tests\Stream\Exception;
+
+use GuzzleHttp\Stream\Exception\SeekException;
+use GuzzleHttp\Stream\Stream;
+
+class SeekExceptionTest extends \PHPUnit_Framework_TestCase
+{
+ public function testHasStream()
+ {
+ $s = Stream::factory('foo');
+ $e = new SeekException($s, 10);
+ $this->assertSame($s, $e->getStream());
+ $this->assertContains('10', $e->getMessage());
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/tests/FnStreamTest.php b/www/wiki/vendor/guzzlehttp/streams/tests/FnStreamTest.php
new file mode 100644
index 00000000..6cc336b9
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/tests/FnStreamTest.php
@@ -0,0 +1,89 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\Stream;
+use GuzzleHttp\Stream\FnStream;
+
+/**
+ * @covers GuzzleHttp\Stream\FnStream
+ */
+class FnStreamTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException \BadMethodCallException
+ * @expectedExceptionMessage seek() is not implemented in the FnStream
+ */
+ public function testThrowsWhenNotImplemented()
+ {
+ (new FnStream([]))->seek(1);
+ }
+
+ public function testProxiesToFunction()
+ {
+ $s = new FnStream([
+ 'read' => function ($len) {
+ $this->assertEquals(3, $len);
+ return 'foo';
+ }
+ ]);
+
+ $this->assertEquals('foo', $s->read(3));
+ }
+
+ public function testCanCloseOnDestruct()
+ {
+ $called = false;
+ $s = new FnStream([
+ 'close' => function () use (&$called) {
+ $called = true;
+ }
+ ]);
+ unset($s);
+ $this->assertTrue($called);
+ }
+
+ public function testDoesNotRequireClose()
+ {
+ $s = new FnStream([]);
+ unset($s);
+ }
+
+ public function testDecoratesStream()
+ {
+ $a = Stream::factory('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->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 = Stream::factory('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/www/wiki/vendor/guzzlehttp/streams/tests/GuzzleStreamWrapperTest.php b/www/wiki/vendor/guzzlehttp/streams/tests/GuzzleStreamWrapperTest.php
new file mode 100644
index 00000000..33c3eccb
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/tests/GuzzleStreamWrapperTest.php
@@ -0,0 +1,99 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\GuzzleStreamWrapper;
+use GuzzleHttp\Stream\Stream;
+
+/**
+ * @covers GuzzleHttp\Stream\GuzzleStreamWrapper
+ */
+class GuzzleStreamWrapperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testResource()
+ {
+ $stream = Stream::factory('foo');
+ $handle = GuzzleStreamWrapper::getResource($stream);
+ $this->assertSame('foo', fread($handle, 3));
+ $this->assertSame(3, ftell($handle));
+ $this->assertSame(3, fwrite($handle, 'bar'));
+ $this->assertSame(0, fseek($handle, 0));
+ $this->assertSame('foobar', fread($handle, 6));
+ $this->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('GuzzleHttp\Stream\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));
+ GuzzleStreamWrapper::getResource($stream);
+ }
+
+ /**
+ * @expectedException \PHPUnit_Framework_Error_Warning
+ */
+ public function testReturnsFalseWhenStreamDoesNotExist()
+ {
+ fopen('guzzle://foo', 'r');
+ }
+
+ public function testCanOpenReadonlyStream()
+ {
+ $stream = $this->getMockBuilder('GuzzleHttp\Stream\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 = GuzzleStreamWrapper::getResource($stream);
+ $this->assertInternalType('resource', $r);
+ fclose($r);
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/tests/InflateStreamTest.php b/www/wiki/vendor/guzzlehttp/streams/tests/InflateStreamTest.php
new file mode 100644
index 00000000..ead9356a
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/tests/InflateStreamTest.php
@@ -0,0 +1,16 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\InflateStream;
+use GuzzleHttp\Stream\Stream;
+
+class InflateStreamtest extends \PHPUnit_Framework_TestCase
+{
+ public function testInflatesStreams()
+ {
+ $content = gzencode('test');
+ $a = Stream::factory($content);
+ $b = new InflateStream($a);
+ $this->assertEquals('test', (string) $b);
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/tests/LazyOpenStreamTest.php b/www/wiki/vendor/guzzlehttp/streams/tests/LazyOpenStreamTest.php
new file mode 100644
index 00000000..79e0078e
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/tests/LazyOpenStreamTest.php
@@ -0,0 +1,64 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\LazyOpenStream;
+
+class LazyOpenStreamTest extends \PHPUnit_Framework_TestCase
+{
+ private $fname;
+
+ public function setup()
+ {
+ $this->fname = tempnam('/tmp', 'tfile');
+
+ if (file_exists($this->fname)) {
+ unlink($this->fname);
+ }
+ }
+
+ public function tearDown()
+ {
+ if (file_exists($this->fname)) {
+ unlink($this->fname);
+ }
+ }
+
+ public function testOpensLazily()
+ {
+ $l = new LazyOpenStream($this->fname, 'w+');
+ $l->write('foo');
+ $this->assertInternalType('array', $l->getMetadata());
+ $this->assertFileExists($this->fname);
+ $this->assertEquals('foo', file_get_contents($this->fname));
+ $this->assertEquals('foo', (string) $l);
+ }
+
+ public function testProxiesToFile()
+ {
+ file_put_contents($this->fname, 'foo');
+ $l = new LazyOpenStream($this->fname, 'r');
+ $this->assertEquals('foo', $l->read(4));
+ $this->assertTrue($l->eof());
+ $this->assertEquals(3, $l->tell());
+ $this->assertTrue($l->isReadable());
+ $this->assertTrue($l->isSeekable());
+ $this->assertFalse($l->isWritable());
+ $l->seek(1);
+ $this->assertEquals('oo', $l->getContents());
+ $this->assertEquals('foo', (string) $l);
+ $this->assertEquals(3, $l->getSize());
+ $this->assertInternalType('array', $l->getMetadata());
+ $l->close();
+ }
+
+ public function testDetachesUnderlyingStream()
+ {
+ file_put_contents($this->fname, 'foo');
+ $l = new LazyOpenStream($this->fname, 'r');
+ $r = $l->detach();
+ $this->assertInternalType('resource', $r);
+ fseek($r, 0);
+ $this->assertEquals('foo', stream_get_contents($r));
+ fclose($r);
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/tests/LimitStreamTest.php b/www/wiki/vendor/guzzlehttp/streams/tests/LimitStreamTest.php
new file mode 100644
index 00000000..efb1dc58
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/tests/LimitStreamTest.php
@@ -0,0 +1,133 @@
+<?php
+namespace GuzzleHttp\Tests\Http;
+
+use GuzzleHttp\Stream\FnStream;
+use GuzzleHttp\Stream\Stream;
+use GuzzleHttp\Stream\LimitStream;
+use GuzzleHttp\Stream\NoSeekStream;
+
+/**
+ * @covers GuzzleHttp\Stream\LimitStream
+ */
+class LimitStreamTest extends \PHPUnit_Framework_TestCase
+{
+ /** @var LimitStream */
+ protected $body;
+
+ /** @var Stream */
+ protected $decorated;
+
+ public function setUp()
+ {
+ $this->decorated = Stream::factory(fopen(__FILE__, 'r'));
+ $this->body = new LimitStream($this->decorated, 10, 3);
+ }
+
+ public function testReturnsSubset()
+ {
+ $body = new LimitStream(Stream::factory('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->assertTrue($body->eof());
+ }
+
+ public function testReturnsSubsetWhenCastToString()
+ {
+ $body = Stream::factory('foo_baz_bar');
+ $limited = new LimitStream($body, 3, 4);
+ $this->assertEquals('baz', (string) $limited);
+ }
+
+ public function testReturnsSubsetOfEmptyBodyWhenCastToString()
+ {
+ $body = Stream::factory('');
+ $limited = new LimitStream($body, 0, 10);
+ $this->assertEquals('', (string) $limited);
+ }
+
+ public function testSeeksWhenConstructed()
+ {
+ $this->assertEquals(0, $this->body->tell());
+ $this->assertEquals(3, $this->decorated->tell());
+ }
+
+ public function testAllowsBoundedSeek()
+ {
+ $this->assertEquals(true, $this->body->seek(100));
+ $this->assertEquals(10, $this->body->tell());
+ $this->assertEquals(13, $this->decorated->tell());
+ $this->assertEquals(true, $this->body->seek(0));
+ $this->assertEquals(0, $this->body->tell());
+ $this->assertEquals(3, $this->decorated->tell());
+ $this->assertEquals(false, $this->body->seek(-10));
+ $this->assertEquals(0, $this->body->tell());
+ $this->assertEquals(3, $this->decorated->tell());
+ $this->assertEquals(true, $this->body->seek(5));
+ $this->assertEquals(5, $this->body->tell());
+ $this->assertEquals(8, $this->decorated->tell());
+ $this->assertEquals(false, $this->body->seek(1000, SEEK_END));
+ }
+
+ public function testReadsOnlySubsetOfData()
+ {
+ $data = $this->body->read(100);
+ $this->assertEquals(10, strlen($data));
+ $this->assertFalse($this->body->read(1000));
+
+ $this->body->setOffset(10);
+ $newData = $this->body->read(100);
+ $this->assertEquals(10, strlen($newData));
+ $this->assertNotSame($data, $newData);
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Stream\Exception\SeekException
+ * @expectedExceptionMessage Could not seek the stream to position 2
+ */
+ public function testThrowsWhenCurrentGreaterThanOffsetSeek()
+ {
+ $a = Stream::factory('foo_bar');
+ $b = new NoSeekStream($a);
+ $c = new LimitStream($b);
+ $a->getContents();
+ $c->setOffset(2);
+ }
+
+ 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(Stream::factory('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 = Stream::factory('foo_bar');
+ $b = new LimitStream($a, -1, 4);
+ $this->assertEquals(3, $b->getSize());
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/tests/NoSeekStreamTest.php b/www/wiki/vendor/guzzlehttp/streams/tests/NoSeekStreamTest.php
new file mode 100644
index 00000000..21b7c6d2
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/tests/NoSeekStreamTest.php
@@ -0,0 +1,41 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\Stream;
+use GuzzleHttp\Stream\NoSeekStream;
+
+/**
+ * @covers GuzzleHttp\Stream\NoSeekStream
+ * @covers GuzzleHttp\Stream\StreamDecoratorTrait
+ */
+class NoSeekStreamTest extends \PHPUnit_Framework_TestCase
+{
+ public function testCannotSeek()
+ {
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\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());
+ $this->assertFalse($wrapped->seek(2));
+ }
+
+ public function testHandlesClose()
+ {
+ $s = Stream::factory('foo');
+ $wrapped = new NoSeekStream($s);
+ $wrapped->close();
+ $this->assertFalse($wrapped->write('foo'));
+ }
+
+ public function testCanAttach()
+ {
+ $s1 = Stream::factory('foo');
+ $s2 = Stream::factory('bar');
+ $wrapped = new NoSeekStream($s1);
+ $wrapped->attach($s2->detach());
+ $this->assertEquals('bar', (string) $wrapped);
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/tests/NullStreamTest.php b/www/wiki/vendor/guzzlehttp/streams/tests/NullStreamTest.php
new file mode 100644
index 00000000..8e414315
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/tests/NullStreamTest.php
@@ -0,0 +1,39 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\NullStream;
+
+class NullStreamTest extends \PHPUnit_Framework_TestCase
+{
+ public function testDoesNothing()
+ {
+ $b = new NullStream();
+ $this->assertEquals('', $b->read(10));
+ $this->assertEquals(4, $b->write('test'));
+ $this->assertEquals('', (string) $b);
+ $this->assertNull($b->getMetadata('a'));
+ $this->assertEquals([], $b->getMetadata());
+ $this->assertEquals(0, $b->getSize());
+ $this->assertEquals('', $b->getContents());
+ $this->assertEquals(0, $b->tell());
+
+ $this->assertTrue($b->isReadable());
+ $this->assertTrue($b->isWritable());
+ $this->assertTrue($b->isSeekable());
+ $this->assertFalse($b->seek(10));
+
+ $this->assertTrue($b->eof());
+ $b->detach();
+ $this->assertTrue($b->eof());
+ $b->close();
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Stream\Exception\CannotAttachException
+ */
+ public function testCannotAttach()
+ {
+ $p = new NullStream();
+ $p->attach('a');
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/tests/PumpStreamTest.php b/www/wiki/vendor/guzzlehttp/streams/tests/PumpStreamTest.php
new file mode 100644
index 00000000..2d20ce90
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/tests/PumpStreamTest.php
@@ -0,0 +1,77 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\LimitStream;
+use GuzzleHttp\Stream\PumpStream;
+use GuzzleHttp\Stream\Stream;
+
+class PumpStreamTest extends \PHPUnit_Framework_TestCase
+{
+ public function testHasMetadataAndSize()
+ {
+ $p = new PumpStream(function () {}, [
+ 'metadata' => ['foo' => 'bar'],
+ 'size' => 100
+ ]);
+
+ $this->assertEquals('bar', $p->getMetadata('foo'));
+ $this->assertEquals(['foo' => 'bar'], $p->getMetadata());
+ $this->assertEquals(100, $p->getSize());
+ }
+
+ public function testCanReadFromCallable()
+ {
+ $p = Stream::factory(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 = Stream::factory(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 = Stream::factory(function () { return 'a'; });
+ $s = new LimitStream($p, 5);
+ $this->assertEquals('aaaaa', (string) $s);
+ }
+
+ public function testDescribesCapabilities()
+ {
+ $p = Stream::factory(function () {});
+ $this->assertTrue($p->isReadable());
+ $this->assertFalse($p->isSeekable());
+ $this->assertFalse($p->isWritable());
+ $this->assertNull($p->getSize());
+ $this->assertFalse($p->write('aa'));
+ $this->assertEquals('', $p->getContents());
+ $this->assertEquals('', (string) $p);
+ $p->close();
+ $this->assertEquals('', $p->read(10));
+ $this->assertTrue($p->eof());
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Stream\Exception\CannotAttachException
+ */
+ public function testCannotAttach()
+ {
+ $p = Stream::factory(function () {});
+ $p->attach('a');
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/tests/StreamDecoratorTraitTest.php b/www/wiki/vendor/guzzlehttp/streams/tests/StreamDecoratorTraitTest.php
new file mode 100644
index 00000000..2ba79add
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/tests/StreamDecoratorTraitTest.php
@@ -0,0 +1,147 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\StreamInterface;
+use GuzzleHttp\Stream\Stream;
+use GuzzleHttp\Stream\StreamDecoratorTrait;
+
+class Str implements StreamInterface
+{
+ use StreamDecoratorTrait;
+}
+
+/**
+ * @covers GuzzleHttp\Stream\StreamDecoratorTrait
+ */
+class StreamDecoratorTraitTest extends \PHPUnit_Framework_TestCase
+{
+ private $a;
+ private $b;
+ private $c;
+
+ public function setUp()
+ {
+ $this->c = fopen('php://temp', 'r+');
+ fwrite($this->c, 'foo');
+ fseek($this->c, 0);
+ $this->a = Stream::factory($this->c);
+ $this->b = new Str($this->a);
+ }
+
+ public function testCatchesExceptionsWhenCastingToString()
+ {
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\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());
+ $this->assertSame($this->b, $this->b->setSize(2));
+ $this->assertEquals(2, $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->assertTrue($this->b->seek(1));
+ $this->assertEquals(1, $this->a->tell());
+ $this->assertEquals(1, $this->b->tell());
+ $this->assertTrue($this->b->seek(0));
+ $this->assertEquals(0, $this->a->tell());
+ $this->assertEquals(0, $this->b->tell());
+ $this->assertTrue($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());
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Stream\Exception\CannotAttachException
+ */
+ public function testCannotAttachByDefault()
+ {
+ $this->b->attach('a');
+ }
+
+ 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/www/wiki/vendor/guzzlehttp/streams/tests/StreamTest.php b/www/wiki/vendor/guzzlehttp/streams/tests/StreamTest.php
new file mode 100644
index 00000000..2985bfbb
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/tests/StreamTest.php
@@ -0,0 +1,252 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\Stream;
+
+/**
+ * @covers GuzzleHttp\Stream\Stream
+ */
+class StreamTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testConstructorThrowsExceptionOnInvalidArgument()
+ {
+ new Stream(true);
+ }
+
+ public function testConstructorInitializesProperties()
+ {
+ $handle = fopen('php://temp', 'r+');
+ fwrite($handle, 'data');
+ $stream = new Stream($handle);
+ $this->assertTrue($stream->isReadable());
+ $this->assertTrue($stream->isWritable());
+ $this->assertTrue($stream->isSeekable());
+ $this->assertEquals('php://temp', $stream->getMetadata('uri'));
+ $this->assertInternalType('array', $stream->getMetadata());
+ $this->assertEquals(4, $stream->getSize());
+ $this->assertFalse($stream->eof());
+ $stream->close();
+ }
+
+ public function testStreamClosesHandleOnDestruct()
+ {
+ $handle = fopen('php://temp', 'r');
+ $stream = new Stream($handle);
+ unset($stream);
+ $this->assertFalse(is_resource($handle));
+ }
+
+ public function testConvertsToString()
+ {
+ $handle = fopen('php://temp', 'w+');
+ fwrite($handle, 'data');
+ $stream = new Stream($handle);
+ $this->assertEquals('data', (string) $stream);
+ $this->assertEquals('data', (string) $stream);
+ $stream->close();
+ }
+
+ public function testGetsContents()
+ {
+ $handle = fopen('php://temp', 'w+');
+ fwrite($handle, 'data');
+ $stream = new Stream($handle);
+ $this->assertEquals('', $stream->getContents());
+ $stream->seek(0);
+ $this->assertEquals('data', $stream->getContents());
+ $this->assertEquals('', $stream->getContents());
+ }
+
+ public function testChecksEof()
+ {
+ $handle = fopen('php://temp', 'w+');
+ fwrite($handle, 'data');
+ $stream = new Stream($handle);
+ $this->assertFalse($stream->eof());
+ $stream->read(4);
+ $this->assertTrue($stream->eof());
+ $stream->close();
+ }
+
+ public function testAllowsSettingManualSize()
+ {
+ $handle = fopen('php://temp', 'w+');
+ fwrite($handle, 'data');
+ $stream = new Stream($handle);
+ $stream->setSize(10);
+ $this->assertEquals(10, $stream->getSize());
+ $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 testKeepsPositionOfResource()
+ {
+ $h = fopen(__FILE__, 'r');
+ fseek($h, 10);
+ $stream = Stream::factory($h);
+ $this->assertEquals(10, $stream->tell());
+ $stream->close();
+ }
+
+ public function testCanDetachAndAttachStream()
+ {
+ $r = fopen('php://temp', 'w+');
+ $stream = new Stream($r);
+ $stream->write('foo');
+ $this->assertTrue($stream->isReadable());
+ $this->assertSame($r, $stream->detach());
+ $this->assertNull($stream->detach());
+
+ $this->assertFalse($stream->isReadable());
+ $this->assertFalse($stream->read(10));
+ $this->assertFalse($stream->isWritable());
+ $this->assertFalse($stream->write('bar'));
+ $this->assertFalse($stream->isSeekable());
+ $this->assertFalse($stream->seek(10));
+ $this->assertFalse($stream->tell());
+ $this->assertTrue($stream->eof());
+ $this->assertNull($stream->getSize());
+ $this->assertSame('', (string) $stream);
+ $this->assertSame('', $stream->getContents());
+
+ $stream->attach($r);
+ $stream->seek(0);
+ $this->assertEquals('foo', $stream->getContents());
+ $this->assertTrue($stream->isReadable());
+ $this->assertTrue($stream->isWritable());
+ $this->assertTrue($stream->isSeekable());
+
+ $stream->close();
+ }
+
+ public function testCloseClearProperties()
+ {
+ $handle = fopen('php://temp', 'r+');
+ $stream = new Stream($handle);
+ $stream->close();
+
+ $this->assertEmpty($stream->getMetadata());
+ $this->assertFalse($stream->isSeekable());
+ $this->assertFalse($stream->isReadable());
+ $this->assertFalse($stream->isWritable());
+ $this->assertNull($stream->getSize());
+ }
+
+ public function testCreatesWithFactory()
+ {
+ $stream = Stream::factory('foo');
+ $this->assertInstanceOf('GuzzleHttp\Stream\Stream', $stream);
+ $this->assertEquals('foo', $stream->getContents());
+ $stream->close();
+ }
+
+ public function testFactoryCreatesFromEmptyString()
+ {
+ $s = Stream::factory();
+ $this->assertInstanceOf('GuzzleHttp\Stream\Stream', $s);
+ }
+
+ public function testFactoryCreatesFromResource()
+ {
+ $r = fopen(__FILE__, 'r');
+ $s = Stream::factory($r);
+ $this->assertInstanceOf('GuzzleHttp\Stream\Stream', $s);
+ $this->assertSame(file_get_contents(__FILE__), (string) $s);
+ }
+
+ public function testFactoryCreatesFromObjectWithToString()
+ {
+ $r = new HasToString();
+ $s = Stream::factory($r);
+ $this->assertInstanceOf('GuzzleHttp\Stream\Stream', $s);
+ $this->assertEquals('foo', (string) $s);
+ }
+
+ public function testCreatePassesThrough()
+ {
+ $s = Stream::factory('foo');
+ $this->assertSame($s, Stream::factory($s));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testThrowsExceptionForUnknown()
+ {
+ Stream::factory(new \stdClass());
+ }
+
+ public function testReturnsCustomMetadata()
+ {
+ $s = Stream::factory('foo', ['metadata' => ['hwm' => 3]]);
+ $this->assertEquals(3, $s->getMetadata('hwm'));
+ $this->assertArrayHasKey('hwm', $s->getMetadata());
+ }
+
+ public function testCanSetSize()
+ {
+ $s = Stream::factory('', ['size' => 10]);
+ $this->assertEquals(10, $s->getSize());
+ }
+
+ public function testCanCreateIteratorBasedStream()
+ {
+ $a = new \ArrayIterator(['foo', 'bar', '123']);
+ $p = Stream::factory($a);
+ $this->assertInstanceOf('GuzzleHttp\Stream\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());
+ }
+}
+
+class HasToString
+{
+ public function __toString() {
+ return 'foo';
+ }
+}
diff --git a/www/wiki/vendor/guzzlehttp/streams/tests/UtilsTest.php b/www/wiki/vendor/guzzlehttp/streams/tests/UtilsTest.php
new file mode 100644
index 00000000..6e3e3b21
--- /dev/null
+++ b/www/wiki/vendor/guzzlehttp/streams/tests/UtilsTest.php
@@ -0,0 +1,155 @@
+<?php
+namespace GuzzleHttp\Tests\Stream;
+
+use GuzzleHttp\Stream\FnStream;
+use GuzzleHttp\Stream\NoSeekStream;
+use GuzzleHttp\Stream\Stream;
+use GuzzleHttp\Stream\Utils;
+
+class UtilsTest extends \PHPUnit_Framework_TestCase
+{
+ public function testCopiesToString()
+ {
+ $s = Stream::factory('foobaz');
+ $this->assertEquals('foobaz', Utils::copyToString($s));
+ $s->seek(0);
+ $this->assertEquals('foo', Utils::copyToString($s, 3));
+ $this->assertEquals('baz', Utils::copyToString($s, 3));
+ $this->assertEquals('', Utils::copyToString($s));
+ }
+
+ public function testCopiesToStringStopsWhenReadFails()
+ {
+ $s1 = Stream::factory('foobaz');
+ $s1 = FnStream::decorate($s1, [
+ 'read' => function () {
+ return false;
+ }
+ ]);
+ $result = Utils::copyToString($s1);
+ $this->assertEquals('', $result);
+ }
+
+ public function testCopiesToStream()
+ {
+ $s1 = Stream::factory('foobaz');
+ $s2 = Stream::factory('');
+ Utils::copyToStream($s1, $s2);
+ $this->assertEquals('foobaz', (string) $s2);
+ $s2 = Stream::factory('');
+ $s1->seek(0);
+ Utils::copyToStream($s1, $s2, 3);
+ $this->assertEquals('foo', (string) $s2);
+ Utils::copyToStream($s1, $s2, 3);
+ $this->assertEquals('foobaz', (string) $s2);
+ }
+
+ public function testStopsCopyToStreamWhenWriteFails()
+ {
+ $s1 = Stream::factory('foobaz');
+ $s2 = Stream::factory('');
+ $s2 = FnStream::decorate($s2, ['write' => function () { return 0; }]);
+ Utils::copyToStream($s1, $s2);
+ $this->assertEquals('', (string) $s2);
+ }
+
+ public function testStopsCopyToSteamWhenWriteFailsWithMaxLen()
+ {
+ $s1 = Stream::factory('foobaz');
+ $s2 = Stream::factory('');
+ $s2 = FnStream::decorate($s2, ['write' => function () { return 0; }]);
+ Utils::copyToStream($s1, $s2, 10);
+ $this->assertEquals('', (string) $s2);
+ }
+
+ public function testStopsCopyToSteamWhenReadFailsWithMaxLen()
+ {
+ $s1 = Stream::factory('foobaz');
+ $s1 = FnStream::decorate($s1, ['read' => function () { return ''; }]);
+ $s2 = Stream::factory('');
+ Utils::copyToStream($s1, $s2, 10);
+ $this->assertEquals('', (string) $s2);
+ }
+
+ public function testReadsLines()
+ {
+ $s = Stream::factory("foo\nbaz\nbar");
+ $this->assertEquals("foo\n", Utils::readline($s));
+ $this->assertEquals("baz\n", Utils::readline($s));
+ $this->assertEquals("bar", Utils::readline($s));
+ }
+
+ public function testReadsLinesUpToMaxLength()
+ {
+ $s = Stream::factory("12345\n");
+ $this->assertEquals("123", Utils::readline($s, 4));
+ $this->assertEquals("45\n", Utils::readline($s));
+ }
+
+ public function testReadsLineUntilFalseReturnedFromRead()
+ {
+ $s = $this->getMockBuilder('GuzzleHttp\Stream\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", Utils::readline($s));
+ }
+
+ public function testCalculatesHash()
+ {
+ $s = Stream::factory('foobazbar');
+ $this->assertEquals(md5('foobazbar'), Utils::hash($s, 'md5'));
+ }
+
+ /**
+ * @expectedException \GuzzleHttp\Stream\Exception\SeekException
+ */
+ public function testCalculatesHashThrowsWhenSeekFails()
+ {
+ $s = new NoSeekStream(Stream::factory('foobazbar'));
+ $s->read(2);
+ Utils::hash($s, 'md5');
+ }
+
+ public function testCalculatesHashSeeksToOriginalPosition()
+ {
+ $s = Stream::factory('foobazbar');
+ $s->seek(4);
+ $this->assertEquals(md5('foobazbar'), Utils::hash($s, 'md5'));
+ $this->assertEquals(4, $s->tell());
+ }
+
+ public function testOpensFilesSuccessfully()
+ {
+ $r = Utils::open(__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()
+ {
+ Utils::open('/path/to/does/not/exist', 'r');
+ }
+
+ public function testProxiesToFactory()
+ {
+ $this->assertEquals('foo', (string) Utils::create('foo'));
+ }
+}