aboutsummaryrefslogtreecommitdiffhomepage
path: root/assets/php/vendor/cboden/ratchet
diff options
context:
space:
mode:
authormarvin-borner@live.com2018-04-10 21:50:16 +0200
committermarvin-borner@live.com2018-04-10 21:54:48 +0200
commitfc9401f04a3aca5abb22f87ebc210de8afe11d32 (patch)
treeb0b310f3581764ec3955f4e496a05137a32951c3 /assets/php/vendor/cboden/ratchet
parent286d643180672f20526f3dc3bd19d7b751e2fa97 (diff)
Initial Commit
Diffstat (limited to 'assets/php/vendor/cboden/ratchet')
-rw-r--r--assets/php/vendor/cboden/ratchet/.gitignore5
-rw-r--r--assets/php/vendor/cboden/ratchet/.travis.yml20
-rw-r--r--assets/php/vendor/cboden/ratchet/CHANGELOG.md135
-rw-r--r--assets/php/vendor/cboden/ratchet/LICENSE19
-rw-r--r--assets/php/vendor/cboden/ratchet/Makefile42
-rw-r--r--assets/php/vendor/cboden/ratchet/README.md83
-rw-r--r--assets/php/vendor/cboden/ratchet/composer.json36
-rw-r--r--assets/php/vendor/cboden/ratchet/phpunit.xml.dist30
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/AbstractConnectionDecorator.php41
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/App.php145
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/ComponentInterface.php31
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/ConnectionInterface.php26
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Http/CloseResponseTrait.php22
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Http/HttpRequestParser.php64
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Http/HttpServer.php76
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Http/HttpServerInterface.php14
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Http/NoOpHttpServerController.php18
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Http/OriginCheck.php65
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Http/Router.php96
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/MessageComponentInterface.php5
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/MessageInterface.php12
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Server/EchoServer.php23
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Server/FlashPolicy.php200
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Server/IoConnection.php38
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Server/IoServer.php140
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Server/IpBlackList.php111
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Serialize/HandlerInterface.php16
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Serialize/PhpBinaryHandler.php33
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Serialize/PhpHandler.php49
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Session/SessionProvider.php243
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Storage/Proxy/VirtualProxy.php54
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Storage/VirtualSessionStorage.php88
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/Exception.php5
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/JsonException.php31
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/ServerProtocol.php161
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/Topic.php99
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/TopicManager.php125
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampConnection.php115
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServer.php67
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServerInterface.php43
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/ConnContext.php20
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/MessageCallableInterface.php8
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/MessageComponentInterface.php6
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/WsConnection.php45
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/WsServer.php225
-rw-r--r--assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/WsServerInterface.php14
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/autobahn/bin/fuzzingserver.php36
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-all.json15
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-profile.json12
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-quick.json12
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/bootstrap.php4
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/AbstractMessageComponentTestCase.php50
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/Component.php35
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/Connection.php20
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/ConnectionDecorator.php22
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/WampComponent.php43
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/NullComponent.php28
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Wamp/Stub/WsWampServerInterface.php7
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/WebSocket/Stub/WsMessageComponentInterface.php7
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/unit/AbstractConnectionDecoratorTest.php147
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/unit/Http/HttpRequestParserTest.php50
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/unit/Http/HttpServerTest.php64
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/unit/Http/OriginCheckTest.php46
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/unit/Http/RouterTest.php165
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/unit/Server/EchoServerTest.php26
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/unit/Server/FlashPolicyComponentTest.php152
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/unit/Server/IoConnectionTest.php32
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/unit/Server/IoServerTest.php118
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/unit/Server/IpBlackListComponentTest.php125
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/unit/Session/Serialize/PhpHandlerTest.php43
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/unit/Session/SessionComponentTest.php124
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/unit/Session/Storage/VirtualSessionStoragePDOTest.php53
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/unit/Wamp/ServerProtocolTest.php295
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/unit/Wamp/TopicManagerTest.php226
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/unit/Wamp/TopicTest.php164
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/unit/Wamp/WampConnectionTest.php77
-rw-r--r--assets/php/vendor/cboden/ratchet/tests/unit/Wamp/WampServerTest.php49
77 files changed, 5191 insertions, 0 deletions
diff --git a/assets/php/vendor/cboden/ratchet/.gitignore b/assets/php/vendor/cboden/ratchet/.gitignore
new file mode 100644
index 0000000..793ef58
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/.gitignore
@@ -0,0 +1,5 @@
+phpunit.xml
+reports
+sandbox
+vendor
+composer.lock \ No newline at end of file
diff --git a/assets/php/vendor/cboden/ratchet/.travis.yml b/assets/php/vendor/cboden/ratchet/.travis.yml
new file mode 100644
index 0000000..6c0dc15
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/.travis.yml
@@ -0,0 +1,20 @@
+language: php
+
+php:
+ - 5.4
+ - 5.5
+ - 5.6
+ - 7.0
+ - 7.1
+ - hhvm
+
+dist: trusty
+
+matrix:
+ allow_failures:
+ - php: hhvm
+
+before_script:
+ - sh -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then echo "session.serialize_handler = php" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi;'
+ - php -m
+ - composer install --dev --prefer-source
diff --git a/assets/php/vendor/cboden/ratchet/CHANGELOG.md b/assets/php/vendor/cboden/ratchet/CHANGELOG.md
new file mode 100644
index 0000000..5169993
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/CHANGELOG.md
@@ -0,0 +1,135 @@
+CHANGELOG
+=========
+
+### Legend
+
+* "BC": Backwards compatibility break (from public component APIs)
+* "BF": Bug fix
+
+---
+
+* 0.4.1 (2017-12-11)
+ * Only enableKeepAlive in App if no WsServer passed allowing user to set their own timeout duration
+ * Support Symfony 4
+ * BF: Plug NOOP controller in connection from router in case of misbehaving client
+ * BF: Raise error from invalid WAMP payload
+
+* 0.4 (2017-09-14)
+ * BC: $conn->WebSocket->request replaced with $conn->httpRequest which is a PSR-7 object
+ * Binary messages now supported via Ratchet\WebSocket\MessageComponentInterface
+ * Added heartbeat support via ping/pong in WsServer
+ * BC: No longer support old (and insecure) Hixie76 and Hybi protocols
+ * BC: No longer support disabling UTF-8 checks
+ * BC: The Session component implements HttpServerInterface instead of WsServerInterface
+ * BC: PHP 5.3 no longer supported
+ * BC: Update to newer version of react/socket dependency
+ * BC: WAMP topics reduced to 0 subscriptions are deleted, new subs to same name will result in new Topic instance
+ * Significant performance enhancements
+
+* 0.3.6 (2017-01-06)
+ * BF: Keep host and scheme in HTTP request object attatched to connection
+ * BF: Return correct HTTP response (405) when non-GET request made
+
+* 0.3.5 (2016-05-25)
+ * BF: Unmask responding close frame
+ * Added write handler for PHP session serializer
+
+* 0.3.4 (2015-12-23)
+ * BF: Edge case where version check wasn't run on message coalesce
+ * BF: Session didn't start when using pdo_sqlite
+ * BF: WAMP currie prefix check when using '#'
+ * Compatibility with Symfony 3
+
+* 0.3.3 (2015-05-26)
+ * BF: Framing bug on large messages upon TCP fragmentation
+ * BF: Symfony Router query parameter defaults applied to Request
+ * BF: WAMP CURIE on all URIs
+ * OriginCheck rules applied to FlashPolicy
+ * Switched from PSR-0 to PSR-4
+
+* 0.3.2 (2014-06-08)
+ * BF: No messages after closing handshake (fixed rare race condition causing 100% CPU)
+ * BF: Fixed accidental BC break from v0.3.1
+ * Added autoDelete parameter to Topic to destroy when empty of connections
+ * Exposed React Socket on IoServer (allowing FlashPolicy shutdown in App)
+ * Normalized Exceptions in WAMP
+
+* 0.3.1 (2014-05-26)
+ * Added query parameter support to Router, set in HTTP request (ws://server?hello=world)
+ * HHVM compatibility
+ * BF: React/0.4 support; CPU starvation bug fixes
+ * BF: Allow App::route to ignore Host header
+ * Added expected filters to WAMP Topic broadcast method
+ * Resource cleanup in WAMP TopicManager
+
+* 0.3.0 (2013-10-14)
+ * Added the `App` class to help making Ratchet so easy to use it's silly
+ * BC: Require hostname to do HTTP Host header match and do Origin HTTP header check, verify same name by default, helping prevent CSRF attacks
+ * Added Symfony/2.2 based HTTP Router component to allowing for a single Ratchet server to handle multiple apps -> Ratchet\Http\Router
+ * BC: Decoupled HTTP from WebSocket component -> Ratchet\Http\HttpServer
+ * BF: Single sub-protocol selection to conform with RFC6455
+ * BF: Sanity checks on WAMP protocol to prevent errors
+
+* 0.2.8 (2013-09-19)
+ * React 0.3 support
+
+* 0.2.7 (2013-06-09)
+ * BF: Sub-protocol negotation with Guzzle 3.6
+
+* 0.2.6 (2013-06-01)
+ * Guzzle 3.6 support
+
+* 0.2.5 (2013-04-01)
+ * Fixed Hixie-76 handshake bug
+
+* 0.2.4 (2013-03-09)
+ * Support for Symfony 2.2 and Guzzle 2.3
+ * Minor bug fixes when handling errors
+
+* 0.2.3 (2012-11-21)
+ * Bumped dep: Guzzle to v3, React to v0.2.4
+ * More tests
+
+* 0.2.2 (2012-10-20)
+ * Bumped deps to use React v0.2
+
+* 0.2.1 (2012-10-13)
+ * BF: No more UTF-8 warnings in browsers (no longer sending empty sub-protocol string)
+ * Documentation corrections
+ * Using new composer structure
+
+* 0.2 (2012-09-07)
+ * Ratchet passes every non-binary-frame test from the Autobahn Testsuite
+ * Major performance improvements
+ * BC: Renamed "WampServer" to "ServerProtocol"
+ * BC: New "WampServer" component passes Topic container objects of subscribed Connections
+ * Option to turn off UTF-8 checks in order to increase performance
+ * Switched dependency guzzle/guzzle to guzzle/http (no API changes)
+ * mbstring no longer required
+
+* 0.1.5 (2012-07-12)
+ * BF: Error where service wouldn't run on PHP <= 5.3.8
+ * Dependency library updates
+
+* 0.1.4 (2012-06-17)
+ * Fixed dozens of failing AB tests
+ * BF: Proper socket buffer handling
+
+* 0.1.3 (2012-06-15)
+ * Major refactor inside WebSocket protocol handling, more loosley coupled
+ * BF: Proper error handling on failed WebSocket connections
+ * BF: Handle TCP message concatenation
+ * Inclusion of the AutobahnTestSuite checking WebSocket protocol compliance
+ * mb_string now a requirement
+
+* 0.1.2 (2012-05-19)
+ * BC/BF: Updated WAMP API to coincide with the official spec
+ * Tweaks to improve running as a long lived process
+
+* 0.1.1 (2012-05-14)
+ * Separated interfaces allowing WebSockets to support multiple sub protocols
+ * BF: remoteAddress variable on connections returns proper value
+
+* 0.1 (2012-05-11)
+ * First release with components: IoServer, WsServer, SessionProvider, WampServer, FlashPolicy, IpBlackList
+ * I/O now handled by React, making Ratchet fully asynchronous
diff --git a/assets/php/vendor/cboden/ratchet/LICENSE b/assets/php/vendor/cboden/ratchet/LICENSE
new file mode 100644
index 0000000..24abba1
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2011-2017 Chris Boden
+
+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/assets/php/vendor/cboden/ratchet/Makefile b/assets/php/vendor/cboden/ratchet/Makefile
new file mode 100644
index 0000000..a2526c0
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/Makefile
@@ -0,0 +1,42 @@
+# This file is intended to ease the author's development and testing process
+# Users do not need to use `make`; Ratchet does not need to be compiled
+
+test:
+ phpunit
+
+cover:
+ phpunit --coverage-text --coverage-html=reports/coverage
+
+abtests:
+ ulimit -n 2048 && php tests/autobahn/bin/fuzzingserver.php 8001 LibEvent &
+ ulimit -n 2048 && php tests/autobahn/bin/fuzzingserver.php 8002 StreamSelect &
+ ulimit -n 2048 && php tests/autobahn/bin/fuzzingserver.php 8004 LibEv &
+ wstest -m testeeserver -w ws://localhost:8000 &
+ sleep 1
+ wstest -m fuzzingclient -s tests/autobahn/fuzzingclient-all.json
+ killall php wstest
+
+abtest:
+ ulimit -n 2048 && php tests/autobahn/bin/fuzzingserver.php 8000 StreamSelect &
+ sleep 1
+ wstest -m fuzzingclient -s tests/autobahn/fuzzingclient-quick.json
+ killall php
+
+profile:
+ php -d 'xdebug.profiler_enable=1' tests/autobahn/bin/fuzzingserver.php 8000 LibEvent &
+ sleep 1
+ wstest -m fuzzingclient -s tests/autobahn/fuzzingclient-profile.json
+ killall php
+
+apidocs:
+ apigen --title Ratchet -d reports/api \
+ -s src/ \
+ -s vendor/ratchet/rfc6455/src \
+ -s vendor/react/event-loop/src \
+ -s vendor/react/socket/src \
+ -s vendor/react/stream/src \
+ -s vendor/psr/http-message/src \
+ -s vendor/symfony/http-foundation/Session \
+ -s vendor/symfony/routing \
+ -s vendor/evenement/evenement/src/Evenement \
+ --exclude=vendor/symfony/routing/Tests \
diff --git a/assets/php/vendor/cboden/ratchet/README.md b/assets/php/vendor/cboden/ratchet/README.md
new file mode 100644
index 0000000..3f1a345
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/README.md
@@ -0,0 +1,83 @@
+# Ratchet
+
+[![Build Status](https://secure.travis-ci.org/ratchetphp/Ratchet.png?branch=master)](http://travis-ci.org/ratchetphp/Ratchet)
+[![Autobahn Testsuite](https://img.shields.io/badge/Autobahn-passing-brightgreen.svg)](http://socketo.me/reports/ab/index.html)
+[![Latest Stable Version](https://poser.pugx.org/cboden/ratchet/v/stable.png)](https://packagist.org/packages/cboden/ratchet)
+
+A PHP library for asynchronously serving WebSockets.
+Build up your application through simple interfaces and re-use your application without changing any of its code just by combining different components.
+
+## Requirements
+
+Shell access is required and root access is recommended.
+To avoid proxy/firewall blockage it's recommended WebSockets are requested on port 80 or 443 (SSL), which requires root access.
+In order to do this, along with your sync web stack, you can either use a reverse proxy or two separate machines.
+You can find more details in the [server conf docs](http://socketo.me/docs/deploy#serverconfiguration).
+
+### Documentation
+
+User and API documentation is available on Ratchet's website: http://socketo.me
+
+See https://github.com/cboden/Ratchet-examples for some out-of-the-box working demos using Ratchet.
+
+Need help? Have a question? Want to provide feedback? Write a message on the [Google Groups Mailing List](https://groups.google.com/forum/#!forum/ratchet-php).
+
+---
+
+### A quick example
+
+```php
+<?php
+use Ratchet\MessageComponentInterface;
+use Ratchet\ConnectionInterface;
+
+ // Make sure composer dependencies have been installed
+ require __DIR__ . '/vendor/autoload.php';
+
+/**
+ * chat.php
+ * Send any incoming messages to all connected clients (except sender)
+ */
+class MyChat implements MessageComponentInterface {
+ protected $clients;
+
+ public function __construct() {
+ $this->clients = new \SplObjectStorage;
+ }
+
+ public function onOpen(ConnectionInterface $conn) {
+ $this->clients->attach($conn);
+ }
+
+ public function onMessage(ConnectionInterface $from, $msg) {
+ foreach ($this->clients as $client) {
+ if ($from != $client) {
+ $client->send($msg);
+ }
+ }
+ }
+
+ public function onClose(ConnectionInterface $conn) {
+ $this->clients->detach($conn);
+ }
+
+ public function onError(ConnectionInterface $conn, \Exception $e) {
+ $conn->close();
+ }
+}
+
+ // Run the server application through the WebSocket protocol on port 8080
+ $app = new Ratchet\App('localhost', 8080);
+ $app->route('/chat', new MyChat);
+ $app->route('/echo', new Ratchet\Server\EchoServer, array('*'));
+ $app->run();
+```
+
+ $ php chat.php
+
+```javascript
+ // Then some JavaScript in the browser:
+ var conn = new WebSocket('ws://localhost:8080/echo');
+ conn.onmessage = function(e) { console.log(e.data); };
+ conn.onopen = function(e) { conn.send('Hello Me!'); };
+```
diff --git a/assets/php/vendor/cboden/ratchet/composer.json b/assets/php/vendor/cboden/ratchet/composer.json
new file mode 100644
index 0000000..9529618
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/composer.json
@@ -0,0 +1,36 @@
+{
+ "name": "cboden/ratchet"
+ , "type": "library"
+ , "description": "PHP WebSocket library"
+ , "keywords": ["WebSockets", "Server", "Ratchet", "Sockets", "WebSocket"]
+ , "homepage": "http://socketo.me"
+ , "license": "MIT"
+ , "authors": [
+ {
+ "name": "Chris Boden"
+ , "email": "cboden@gmail.com"
+ , "role": "Developer"
+ }
+ ]
+ , "support": {
+ "forum": "https://groups.google.com/forum/#!forum/ratchet-php"
+ , "issues": "https://github.com/ratchetphp/Ratchet/issues"
+ , "irc": "irc://irc.freenode.org/reactphp"
+ }
+ , "autoload": {
+ "psr-4": {
+ "Ratchet\\": "src/Ratchet"
+ }
+ }
+ , "require": {
+ "php": ">=5.4.2"
+ , "ratchet/rfc6455": "^0.2"
+ , "react/socket": "^1.0 || ^0.8 || ^0.7 || ^0.6 || ^0.5"
+ , "guzzlehttp/psr7": "^1.0"
+ , "symfony/http-foundation": "^2.6|^3.0|^4.0"
+ , "symfony/routing": "^2.6|^3.0|^4.0"
+ }
+ , "require-dev": {
+ "phpunit/phpunit": "~4.8"
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/phpunit.xml.dist b/assets/php/vendor/cboden/ratchet/phpunit.xml.dist
new file mode 100644
index 0000000..0cc5451
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/phpunit.xml.dist
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit
+ forceCoversAnnotation="true"
+ mapTestClassNameToCoveredClassName="true"
+ bootstrap="tests/bootstrap.php"
+ colors="true"
+ backupGlobals="false"
+ backupStaticAttributes="false"
+ syntaxCheck="false"
+ stopOnError="false"
+>
+
+ <testsuites>
+ <testsuite name="unit">
+ <directory>./tests/unit/</directory>
+ </testsuite>
+ </testsuites>
+
+ <testsuites>
+ <testsuite name="integration">
+ <directory>./tests/integration/</directory>
+ </testsuite>
+ </testsuites>
+
+ <filter>
+ <whitelist>
+ <directory>./src/</directory>
+ </whitelist>
+ </filter>
+</phpunit> \ No newline at end of file
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/AbstractConnectionDecorator.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/AbstractConnectionDecorator.php
new file mode 100644
index 0000000..9707951
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/AbstractConnectionDecorator.php
@@ -0,0 +1,41 @@
+<?php
+namespace Ratchet;
+
+/**
+ * Wraps ConnectionInterface objects via the decorator pattern but allows
+ * parameters to bubble through with magic methods
+ * @todo It sure would be nice if I could make most of this a trait...
+ */
+abstract class AbstractConnectionDecorator implements ConnectionInterface {
+ /**
+ * @var ConnectionInterface
+ */
+ protected $wrappedConn;
+
+ public function __construct(ConnectionInterface $conn) {
+ $this->wrappedConn = $conn;
+ }
+
+ /**
+ * @return ConnectionInterface
+ */
+ protected function getConnection() {
+ return $this->wrappedConn;
+ }
+
+ public function __set($name, $value) {
+ $this->wrappedConn->$name = $value;
+ }
+
+ public function __get($name) {
+ return $this->wrappedConn->$name;
+ }
+
+ public function __isset($name) {
+ return isset($this->wrappedConn->$name);
+ }
+
+ public function __unset($name) {
+ unset($this->wrappedConn->$name);
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/App.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/App.php
new file mode 100644
index 0000000..f378534
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/App.php
@@ -0,0 +1,145 @@
+<?php
+namespace Ratchet;
+use React\EventLoop\LoopInterface;
+use React\EventLoop\Factory as LoopFactory;
+use React\Socket\Server as Reactor;
+use React\Socket\SecureServer as SecureReactor;
+use Ratchet\Http\HttpServerInterface;
+use Ratchet\Http\OriginCheck;
+use Ratchet\Wamp\WampServerInterface;
+use Ratchet\Server\IoServer;
+use Ratchet\Server\FlashPolicy;
+use Ratchet\Http\HttpServer;
+use Ratchet\Http\Router;
+use Ratchet\WebSocket\WsServer;
+use Ratchet\Wamp\WampServer;
+use Symfony\Component\Routing\RouteCollection;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\Routing\RequestContext;
+use Symfony\Component\Routing\Matcher\UrlMatcher;
+
+/**
+ * An opinionated facade class to quickly and easily create a WebSocket server.
+ * A few configuration assumptions are made and some best-practice security conventions are applied by default.
+ */
+class App {
+ /**
+ * @var \Symfony\Component\Routing\RouteCollection
+ */
+ public $routes;
+
+ /**
+ * @var \Ratchet\Server\IoServer
+ */
+ public $flashServer;
+
+ /**
+ * @var \Ratchet\Server\IoServer
+ */
+ protected $_server;
+
+ /**
+ * The Host passed in construct used for same origin policy
+ * @var string
+ */
+ protected $httpHost;
+
+ /***
+ * The port the socket is listening
+ * @var int
+ */
+ protected $port;
+
+ /**
+ * @var int
+ */
+ protected $_routeCounter = 0;
+
+ /**
+ * @param string $httpHost HTTP hostname clients intend to connect to. MUST match JS `new WebSocket('ws://$httpHost');`
+ * @param int $port Port to listen on. If 80, assuming production, Flash on 843 otherwise expecting Flash to be proxied through 8843
+ * @param string $address IP address to bind to. Default is localhost/proxy only. '0.0.0.0' for any machine.
+ * @param LoopInterface $loop Specific React\EventLoop to bind the application to. null will create one for you.
+ */
+ public function __construct($httpHost = 'localhost', $port = 8080, $address = '127.0.0.1', LoopInterface $loop = null) {
+ if (extension_loaded('xdebug')) {
+ trigger_error('XDebug extension detected. Remember to disable this if performance testing or going live!', E_USER_WARNING);
+ }
+
+ if (null === $loop) {
+ $loop = LoopFactory::create();
+ }
+
+ $this->httpHost = $httpHost;
+ $this->port = $port;
+
+ $socket = new Reactor($address . ':' . $port, $loop);
+
+ $this->routes = new RouteCollection;
+ $this->_server = new IoServer(new HttpServer(new Router(new UrlMatcher($this->routes, new RequestContext))), $socket, $loop);
+
+ $policy = new FlashPolicy;
+ $policy->addAllowedAccess($httpHost, 80);
+ $policy->addAllowedAccess($httpHost, $port);
+
+ if (80 == $port) {
+ $flashUri = '0.0.0.0:843';
+ } else {
+ $flashUri = 8843;
+ }
+ $flashSock = new Reactor($flashUri, $loop);
+ $this->flashServer = new IoServer($policy, $flashSock);
+ }
+
+ /**
+ * Add an endpoint/application to the server
+ * @param string $path The URI the client will connect to
+ * @param ComponentInterface $controller Your application to server for the route. If not specified, assumed to be for a WebSocket
+ * @param array $allowedOrigins An array of hosts allowed to connect (same host by default), ['*'] for any
+ * @param string $httpHost Override the $httpHost variable provided in the __construct
+ * @return ComponentInterface|WsServer
+ */
+ public function route($path, ComponentInterface $controller, array $allowedOrigins = array(), $httpHost = null) {
+ if ($controller instanceof HttpServerInterface || $controller instanceof WsServer) {
+ $decorated = $controller;
+ } elseif ($controller instanceof WampServerInterface) {
+ $decorated = new WsServer(new WampServer($controller));
+ $decorated->enableKeepAlive($this->_server->loop);
+ } elseif ($controller instanceof MessageComponentInterface) {
+ $decorated = new WsServer($controller);
+ $decorated->enableKeepAlive($this->_server->loop);
+ } else {
+ $decorated = $controller;
+ }
+
+ if ($httpHost === null) {
+ $httpHost = $this->httpHost;
+ }
+
+ $allowedOrigins = array_values($allowedOrigins);
+ if (0 === count($allowedOrigins)) {
+ $allowedOrigins[] = $httpHost;
+ }
+ if ('*' !== $allowedOrigins[0]) {
+ $decorated = new OriginCheck($decorated, $allowedOrigins);
+ }
+
+ //allow origins in flash policy server
+ if(empty($this->flashServer) === false) {
+ foreach($allowedOrigins as $allowedOrgin) {
+ $this->flashServer->app->addAllowedAccess($allowedOrgin, $this->port);
+ }
+ }
+
+ $this->routes->add('rr-' . ++$this->_routeCounter, new Route($path, array('_controller' => $decorated), array('Origin' => $this->httpHost), array(), $httpHost, array(), array('GET')));
+
+ return $decorated;
+ }
+
+ /**
+ * Run the server by entering the event loop
+ */
+ public function run() {
+ $this->_server->run();
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/ComponentInterface.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/ComponentInterface.php
new file mode 100644
index 0000000..37e41b1
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/ComponentInterface.php
@@ -0,0 +1,31 @@
+<?php
+namespace Ratchet;
+
+/**
+ * This is the interface to build a Ratchet application with.
+ * It implements the decorator pattern to build an application stack
+ */
+interface ComponentInterface {
+ /**
+ * When a new connection is opened it will be passed to this method
+ * @param ConnectionInterface $conn The socket/connection that just connected to your application
+ * @throws \Exception
+ */
+ function onOpen(ConnectionInterface $conn);
+
+ /**
+ * This is called before or after a socket is closed (depends on how it's closed). SendMessage to $conn will not result in an error if it has already been closed.
+ * @param ConnectionInterface $conn The socket/connection that is closing/closed
+ * @throws \Exception
+ */
+ function onClose(ConnectionInterface $conn);
+
+ /**
+ * If there is an error with one of the sockets, or somewhere in the application where an Exception is thrown,
+ * the Exception is sent back down the stack, handled by the Server and bubbled back up the application through this method
+ * @param ConnectionInterface $conn
+ * @param \Exception $e
+ * @throws \Exception
+ */
+ function onError(ConnectionInterface $conn, \Exception $e);
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/ConnectionInterface.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/ConnectionInterface.php
new file mode 100644
index 0000000..26fb8a4
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/ConnectionInterface.php
@@ -0,0 +1,26 @@
+<?php
+namespace Ratchet;
+
+/**
+ * The version of Ratchet being used
+ * @var string
+ */
+const VERSION = 'Ratchet/0.4.1';
+
+/**
+ * A proxy object representing a connection to the application
+ * This acts as a container to store data (in memory) about the connection
+ */
+interface ConnectionInterface {
+ /**
+ * Send data to the connection
+ * @param string $data
+ * @return \Ratchet\ConnectionInterface
+ */
+ function send($data);
+
+ /**
+ * Close the connection
+ */
+ function close();
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/CloseResponseTrait.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/CloseResponseTrait.php
new file mode 100644
index 0000000..abdf5c4
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/CloseResponseTrait.php
@@ -0,0 +1,22 @@
+<?php
+namespace Ratchet\Http;
+use Ratchet\ConnectionInterface;
+use GuzzleHttp\Psr7 as gPsr;
+use GuzzleHttp\Psr7\Response;
+
+trait CloseResponseTrait {
+ /**
+ * Close a connection with an HTTP response
+ * @param \Ratchet\ConnectionInterface $conn
+ * @param int $code HTTP status code
+ * @return null
+ */
+ private function close(ConnectionInterface $conn, $code = 400, array $additional_headers = []) {
+ $response = new Response($code, array_merge([
+ 'X-Powered-By' => \Ratchet\VERSION
+ ], $additional_headers));
+
+ $conn->send(gPsr\str($response));
+ $conn->close();
+ }
+} \ No newline at end of file
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/HttpRequestParser.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/HttpRequestParser.php
new file mode 100644
index 0000000..9c44114
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/HttpRequestParser.php
@@ -0,0 +1,64 @@
+<?php
+namespace Ratchet\Http;
+use Ratchet\MessageInterface;
+use Ratchet\ConnectionInterface;
+use GuzzleHttp\Psr7 as gPsr;
+
+/**
+ * This class receives streaming data from a client request
+ * and parses HTTP headers, returning a PSR-7 Request object
+ * once it's been buffered
+ */
+class HttpRequestParser implements MessageInterface {
+ const EOM = "\r\n\r\n";
+
+ /**
+ * The maximum number of bytes the request can be
+ * This is a security measure to prevent attacks
+ * @var int
+ */
+ public $maxSize = 4096;
+
+ /**
+ * @param \Ratchet\ConnectionInterface $context
+ * @param string $data Data stream to buffer
+ * @return \Psr\Http\Message\RequestInterface
+ * @throws \OverflowException If the message buffer has become too large
+ */
+ public function onMessage(ConnectionInterface $context, $data) {
+ if (!isset($context->httpBuffer)) {
+ $context->httpBuffer = '';
+ }
+
+ $context->httpBuffer .= $data;
+
+ if (strlen($context->httpBuffer) > (int)$this->maxSize) {
+ throw new \OverflowException("Maximum buffer size of {$this->maxSize} exceeded parsing HTTP header");
+ }
+
+ if ($this->isEom($context->httpBuffer)) {
+ $request = $this->parse($context->httpBuffer);
+
+ unset($context->httpBuffer);
+
+ return $request;
+ }
+ }
+
+ /**
+ * Determine if the message has been buffered as per the HTTP specification
+ * @param string $message
+ * @return boolean
+ */
+ public function isEom($message) {
+ return (boolean)strpos($message, static::EOM);
+ }
+
+ /**
+ * @param string $headers
+ * @return \Psr\Http\Message\RequestInterface
+ */
+ public function parse($headers) {
+ return gPsr\parse_request($headers);
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/HttpServer.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/HttpServer.php
new file mode 100644
index 0000000..bbd8d53
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/HttpServer.php
@@ -0,0 +1,76 @@
+<?php
+namespace Ratchet\Http;
+use Ratchet\MessageComponentInterface;
+use Ratchet\ConnectionInterface;
+
+class HttpServer implements MessageComponentInterface {
+ use CloseResponseTrait;
+
+ /**
+ * Buffers incoming HTTP requests returning a Guzzle Request when coalesced
+ * @var HttpRequestParser
+ * @note May not expose this in the future, may do through facade methods
+ */
+ protected $_reqParser;
+
+ /**
+ * @var \Ratchet\Http\HttpServerInterface
+ */
+ protected $_httpServer;
+
+ /**
+ * @param HttpServerInterface
+ */
+ public function __construct(HttpServerInterface $component) {
+ $this->_httpServer = $component;
+ $this->_reqParser = new HttpRequestParser;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onOpen(ConnectionInterface $conn) {
+ $conn->httpHeadersReceived = false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onMessage(ConnectionInterface $from, $msg) {
+ if (true !== $from->httpHeadersReceived) {
+ try {
+ if (null === ($request = $this->_reqParser->onMessage($from, $msg))) {
+ return;
+ }
+ } catch (\OverflowException $oe) {
+ return $this->close($from, 413);
+ }
+
+ $from->httpHeadersReceived = true;
+
+ return $this->_httpServer->onOpen($from, $request);
+ }
+
+ $this->_httpServer->onMessage($from, $msg);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onClose(ConnectionInterface $conn) {
+ if ($conn->httpHeadersReceived) {
+ $this->_httpServer->onClose($conn);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onError(ConnectionInterface $conn, \Exception $e) {
+ if ($conn->httpHeadersReceived) {
+ $this->_httpServer->onError($conn, $e);
+ } else {
+ $this->close($conn, 500);
+ }
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/HttpServerInterface.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/HttpServerInterface.php
new file mode 100644
index 0000000..2c37c49
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/HttpServerInterface.php
@@ -0,0 +1,14 @@
+<?php
+namespace Ratchet\Http;
+use Ratchet\MessageComponentInterface;
+use Ratchet\ConnectionInterface;
+use Psr\Http\Message\RequestInterface;
+
+interface HttpServerInterface extends MessageComponentInterface {
+ /**
+ * @param \Ratchet\ConnectionInterface $conn
+ * @param \Psr\Http\Message\RequestInterface $request null is default because PHP won't let me overload; don't pass null!!!
+ * @throws \UnexpectedValueException if a RequestInterface is not passed
+ */
+ public function onOpen(ConnectionInterface $conn, RequestInterface $request = null);
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/NoOpHttpServerController.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/NoOpHttpServerController.php
new file mode 100644
index 0000000..4f72e66
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/NoOpHttpServerController.php
@@ -0,0 +1,18 @@
+<?php
+namespace Ratchet\Http;
+use Ratchet\ConnectionInterface;
+use Psr\Http\Message\RequestInterface;
+
+class NoOpHttpServerController implements HttpServerInterface {
+ public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) {
+ }
+
+ public function onMessage(ConnectionInterface $from, $msg) {
+ }
+
+ public function onClose(ConnectionInterface $conn) {
+ }
+
+ public function onError(ConnectionInterface $conn, \Exception $e) {
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/OriginCheck.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/OriginCheck.php
new file mode 100644
index 0000000..2bdc0f7
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/OriginCheck.php
@@ -0,0 +1,65 @@
+<?php
+namespace Ratchet\Http;
+use Ratchet\ConnectionInterface;
+use Ratchet\MessageComponentInterface;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * A middleware to ensure JavaScript clients connecting are from the expected domain.
+ * This protects other websites from open WebSocket connections to your application.
+ * Note: This can be spoofed from non-web browser clients
+ */
+class OriginCheck implements HttpServerInterface {
+ use CloseResponseTrait;
+
+ /**
+ * @var \Ratchet\MessageComponentInterface
+ */
+ protected $_component;
+
+ public $allowedOrigins = [];
+
+ /**
+ * @param MessageComponentInterface $component Component/Application to decorate
+ * @param array $allowed An array of allowed domains that are allowed to connect from
+ */
+ public function __construct(MessageComponentInterface $component, array $allowed = []) {
+ $this->_component = $component;
+ $this->allowedOrigins += $allowed;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) {
+ $header = (string)$request->getHeader('Origin')[0];
+ $origin = parse_url($header, PHP_URL_HOST) ?: $header;
+
+ if (!in_array($origin, $this->allowedOrigins)) {
+ return $this->close($conn, 403);
+ }
+
+ return $this->_component->onOpen($conn, $request);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ function onMessage(ConnectionInterface $from, $msg) {
+ return $this->_component->onMessage($from, $msg);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ function onClose(ConnectionInterface $conn) {
+ return $this->_component->onClose($conn);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ function onError(ConnectionInterface $conn, \Exception $e) {
+ return $this->_component->onError($conn, $e);
+ }
+} \ No newline at end of file
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/Router.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/Router.php
new file mode 100644
index 0000000..df7fe82
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Http/Router.php
@@ -0,0 +1,96 @@
+<?php
+namespace Ratchet\Http;
+use Ratchet\ConnectionInterface;
+use Psr\Http\Message\RequestInterface;
+use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
+use Symfony\Component\Routing\Exception\MethodNotAllowedException;
+use Symfony\Component\Routing\Exception\ResourceNotFoundException;
+use GuzzleHttp\Psr7 as gPsr;
+
+class Router implements HttpServerInterface {
+ use CloseResponseTrait;
+
+ /**
+ * @var \Symfony\Component\Routing\Matcher\UrlMatcherInterface
+ */
+ protected $_matcher;
+
+ private $_noopController;
+
+ public function __construct(UrlMatcherInterface $matcher) {
+ $this->_matcher = $matcher;
+ $this->_noopController = new NoOpHttpServerController;
+ }
+
+ /**
+ * {@inheritdoc}
+ * @throws \UnexpectedValueException If a controller is not \Ratchet\Http\HttpServerInterface
+ */
+ public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) {
+ if (null === $request) {
+ throw new \UnexpectedValueException('$request can not be null');
+ }
+
+ $conn->controller = $this->_noopController;
+
+ $uri = $request->getUri();
+
+ $context = $this->_matcher->getContext();
+ $context->setMethod($request->getMethod());
+ $context->setHost($uri->getHost());
+
+ try {
+ $route = $this->_matcher->match($uri->getPath());
+ } catch (MethodNotAllowedException $nae) {
+ return $this->close($conn, 405, array('Allow' => $nae->getAllowedMethods()));
+ } catch (ResourceNotFoundException $nfe) {
+ return $this->close($conn, 404);
+ }
+
+ if (is_string($route['_controller']) && class_exists($route['_controller'])) {
+ $route['_controller'] = new $route['_controller'];
+ }
+
+ if (!($route['_controller'] instanceof HttpServerInterface)) {
+ throw new \UnexpectedValueException('All routes must implement Ratchet\Http\HttpServerInterface');
+ }
+
+ $parameters = [];
+ foreach($route as $key => $value) {
+ if ((is_string($key)) && ('_' !== substr($key, 0, 1))) {
+ $parameters[$key] = $value;
+ }
+ }
+ $parameters = array_merge($parameters, gPsr\parse_query($uri->getQuery() ?: ''));
+
+ $request = $request->withUri($uri->withQuery(gPsr\build_query($parameters)));
+
+ $conn->controller = $route['_controller'];
+ $conn->controller->onOpen($conn, $request);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onMessage(ConnectionInterface $from, $msg) {
+ $from->controller->onMessage($from, $msg);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onClose(ConnectionInterface $conn) {
+ if (isset($conn->controller)) {
+ $conn->controller->onClose($conn);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onError(ConnectionInterface $conn, \Exception $e) {
+ if (isset($conn->controller)) {
+ $conn->controller->onError($conn, $e);
+ }
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/MessageComponentInterface.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/MessageComponentInterface.php
new file mode 100644
index 0000000..b4a92e2
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/MessageComponentInterface.php
@@ -0,0 +1,5 @@
+<?php
+namespace Ratchet;
+
+interface MessageComponentInterface extends ComponentInterface, MessageInterface {
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/MessageInterface.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/MessageInterface.php
new file mode 100644
index 0000000..1486323
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/MessageInterface.php
@@ -0,0 +1,12 @@
+<?php
+namespace Ratchet;
+
+interface MessageInterface {
+ /**
+ * Triggered when a client sends data through the socket
+ * @param \Ratchet\ConnectionInterface $from The socket/connection that sent the message to your application
+ * @param string $msg The message received
+ * @throws \Exception
+ */
+ function onMessage(ConnectionInterface $from, $msg);
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Server/EchoServer.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Server/EchoServer.php
new file mode 100644
index 0000000..2918e73
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Server/EchoServer.php
@@ -0,0 +1,23 @@
+<?php
+namespace Ratchet\Server;
+use Ratchet\MessageComponentInterface;
+use Ratchet\ConnectionInterface;
+
+/**
+ * A simple Ratchet application that will reply to all messages with the message it received
+ */
+class EchoServer implements MessageComponentInterface {
+ public function onOpen(ConnectionInterface $conn) {
+ }
+
+ public function onMessage(ConnectionInterface $from, $msg) {
+ $from->send($msg);
+ }
+
+ public function onClose(ConnectionInterface $conn) {
+ }
+
+ public function onError(ConnectionInterface $conn, \Exception $e) {
+ $conn->close();
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Server/FlashPolicy.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Server/FlashPolicy.php
new file mode 100644
index 0000000..4a1b8bd
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Server/FlashPolicy.php
@@ -0,0 +1,200 @@
+<?php
+namespace Ratchet\Server;
+use Ratchet\MessageComponentInterface;
+use Ratchet\ConnectionInterface;
+
+/**
+ * An app to go on a server stack to pass a policy file to a Flash socket
+ * Useful if you're using Flash as a WebSocket polyfill on IE
+ * Be sure to run your server instance on port 843
+ * By default this lets accepts everything, make sure you tighten the rules up for production
+ * @final
+ * @link http://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html
+ * @link http://learn.adobe.com/wiki/download/attachments/64389123/CrossDomain_PolicyFile_Specification.pdf?version=1
+ * @link view-source:http://www.adobe.com/xml/schemas/PolicyFileSocket.xsd
+ */
+class FlashPolicy implements MessageComponentInterface {
+
+ /**
+ * Contains the root policy node
+ * @var string
+ */
+ protected $_policy = '<?xml version="1.0"?><!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd"><cross-domain-policy></cross-domain-policy>';
+
+ /**
+ * Stores an array of allowed domains and their ports
+ * @var array
+ */
+ protected $_access = array();
+
+ /**
+ * @var string
+ */
+ protected $_siteControl = '';
+
+ /**
+ * @var string
+ */
+ protected $_cache = '';
+
+ /**
+ * @var string
+ */
+ protected $_cacheValid = false;
+
+ /**
+ * Add a domain to an allowed access list.
+ *
+ * @param string $domain Specifies a requesting domain to be granted access. Both named domains and IP
+ * addresses are acceptable values. Subdomains are considered different domains. A wildcard (*) can
+ * be used to match all domains when used alone, or multiple domains (subdomains) when used as a
+ * prefix for an explicit, second-level domain name separated with a dot (.)
+ * @param string $ports A comma-separated list of ports or range of ports that a socket connection
+ * is allowed to connect to. A range of ports is specified through a dash (-) between two port numbers.
+ * Ranges can be used with individual ports when separated with a comma. A single wildcard (*) can
+ * be used to allow all ports.
+ * @param bool $secure
+ * @throws \UnexpectedValueException
+ * @return FlashPolicy
+ */
+ public function addAllowedAccess($domain, $ports = '*', $secure = false) {
+ if (!$this->validateDomain($domain)) {
+ throw new \UnexpectedValueException('Invalid domain');
+ }
+
+ if (!$this->validatePorts($ports)) {
+ throw new \UnexpectedValueException('Invalid Port');
+ }
+
+ $this->_access[] = array($domain, $ports, (boolean)$secure);
+ $this->_cacheValid = false;
+
+ return $this;
+ }
+
+ /**
+ * Removes all domains from the allowed access list.
+ *
+ * @return \Ratchet\Server\FlashPolicy
+ */
+ public function clearAllowedAccess() {
+ $this->_access = array();
+ $this->_cacheValid = false;
+
+ return $this;
+ }
+
+ /**
+ * site-control defines the meta-policy for the current domain. A meta-policy specifies acceptable
+ * domain policy files other than the master policy file located in the target domain's root and named
+ * crossdomain.xml.
+ *
+ * @param string $permittedCrossDomainPolicies
+ * @throws \UnexpectedValueException
+ * @return FlashPolicy
+ */
+ public function setSiteControl($permittedCrossDomainPolicies = 'all') {
+ if (!$this->validateSiteControl($permittedCrossDomainPolicies)) {
+ throw new \UnexpectedValueException('Invalid site control set');
+ }
+
+ $this->_siteControl = $permittedCrossDomainPolicies;
+ $this->_cacheValid = false;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onOpen(ConnectionInterface $conn) {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onMessage(ConnectionInterface $from, $msg) {
+ if (!$this->_cacheValid) {
+ $this->_cache = $this->renderPolicy()->asXML();
+ $this->_cacheValid = true;
+ }
+
+ $from->send($this->_cache . "\0");
+ $from->close();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onClose(ConnectionInterface $conn) {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onError(ConnectionInterface $conn, \Exception $e) {
+ $conn->close();
+ }
+
+ /**
+ * Builds the crossdomain file based on the template policy
+ *
+ * @throws \UnexpectedValueException
+ * @return \SimpleXMLElement
+ */
+ public function renderPolicy() {
+ $policy = new \SimpleXMLElement($this->_policy);
+
+ $siteControl = $policy->addChild('site-control');
+
+ if ($this->_siteControl == '') {
+ $this->setSiteControl();
+ }
+
+ $siteControl->addAttribute('permitted-cross-domain-policies', $this->_siteControl);
+
+ if (empty($this->_access)) {
+ throw new \UnexpectedValueException('You must add a domain through addAllowedAccess()');
+ }
+
+ foreach ($this->_access as $access) {
+ $tmp = $policy->addChild('allow-access-from');
+ $tmp->addAttribute('domain', $access[0]);
+ $tmp->addAttribute('to-ports', $access[1]);
+ $tmp->addAttribute('secure', ($access[2] === true) ? 'true' : 'false');
+ }
+
+ return $policy;
+ }
+
+ /**
+ * Make sure the proper site control was passed
+ *
+ * @param string $permittedCrossDomainPolicies
+ * @return bool
+ */
+ public function validateSiteControl($permittedCrossDomainPolicies) {
+ //'by-content-type' and 'by-ftp-filename' are not available for sockets
+ return (bool)in_array($permittedCrossDomainPolicies, array('none', 'master-only', 'all'));
+ }
+
+ /**
+ * Validate for proper domains (wildcards allowed)
+ *
+ * @param string $domain
+ * @return bool
+ */
+ public function validateDomain($domain) {
+ return (bool)preg_match("/^((http(s)?:\/\/)?([a-z0-9-_]+\.|\*\.)*([a-z0-9-_\.]+)|\*)$/i", $domain);
+ }
+
+ /**
+ * Make sure valid ports were passed
+ *
+ * @param string $port
+ * @return bool
+ */
+ public function validatePorts($port) {
+ return (bool)preg_match('/^(\*|(\d+[,-]?)*\d+)$/', $port);
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Server/IoConnection.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Server/IoConnection.php
new file mode 100644
index 0000000..9f864bb
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Server/IoConnection.php
@@ -0,0 +1,38 @@
+<?php
+namespace Ratchet\Server;
+use Ratchet\ConnectionInterface;
+use React\Socket\ConnectionInterface as ReactConn;
+
+/**
+ * {@inheritdoc}
+ */
+class IoConnection implements ConnectionInterface {
+ /**
+ * @var \React\Socket\ConnectionInterface
+ */
+ protected $conn;
+
+
+ /**
+ * @param \React\Socket\ConnectionInterface $conn
+ */
+ public function __construct(ReactConn $conn) {
+ $this->conn = $conn;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function send($data) {
+ $this->conn->write($data);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function close() {
+ $this->conn->end();
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Server/IoServer.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Server/IoServer.php
new file mode 100644
index 0000000..b3fb7e0
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Server/IoServer.php
@@ -0,0 +1,140 @@
+<?php
+namespace Ratchet\Server;
+use Ratchet\MessageComponentInterface;
+use React\EventLoop\LoopInterface;
+use React\Socket\ServerInterface;
+use React\EventLoop\Factory as LoopFactory;
+use React\Socket\Server as Reactor;
+use React\Socket\SecureServer as SecureReactor;
+
+/**
+ * Creates an open-ended socket to listen on a port for incoming connections.
+ * Events are delegated through this to attached applications
+ */
+class IoServer {
+ /**
+ * @var \React\EventLoop\LoopInterface
+ */
+ public $loop;
+
+ /**
+ * @var \Ratchet\MessageComponentInterface
+ */
+ public $app;
+
+ /**
+ * The socket server the Ratchet Application is run off of
+ * @var \React\Socket\ServerInterface
+ */
+ public $socket;
+
+ /**
+ * @param \Ratchet\MessageComponentInterface $app The Ratchet application stack to host
+ * @param \React\Socket\ServerInterface $socket The React socket server to run the Ratchet application off of
+ * @param \React\EventLoop\LoopInterface|null $loop The React looper to run the Ratchet application off of
+ */
+ public function __construct(MessageComponentInterface $app, ServerInterface $socket, LoopInterface $loop = null) {
+ if (false === strpos(PHP_VERSION, "hiphop")) {
+ gc_enable();
+ }
+
+ set_time_limit(0);
+ ob_implicit_flush();
+
+ $this->loop = $loop;
+ $this->app = $app;
+ $this->socket = $socket;
+
+ $socket->on('connection', array($this, 'handleConnect'));
+ }
+
+ /**
+ * @param \Ratchet\MessageComponentInterface $component The application that I/O will call when events are received
+ * @param int $port The port to server sockets on
+ * @param string $address The address to receive sockets on (0.0.0.0 means receive connections from any)
+ * @return IoServer
+ */
+ public static function factory(MessageComponentInterface $component, $port = 80, $address = '0.0.0.0') {
+ $loop = LoopFactory::create();
+ $socket = new Reactor($address . ':' . $port, $loop);
+
+ return new static($component, $socket, $loop);
+ }
+
+ /**
+ * Run the application by entering the event loop
+ * @throws \RuntimeException If a loop was not previously specified
+ */
+ public function run() {
+ if (null === $this->loop) {
+ throw new \RuntimeException("A React Loop was not provided during instantiation");
+ }
+
+ // @codeCoverageIgnoreStart
+ $this->loop->run();
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * Triggered when a new connection is received from React
+ * @param \React\Socket\ConnectionInterface $conn
+ */
+ public function handleConnect($conn) {
+ $conn->decor = new IoConnection($conn);
+ $conn->decor->resourceId = (int)$conn->stream;
+
+ $uri = $conn->getRemoteAddress();
+ $conn->decor->remoteAddress = trim(
+ parse_url((strpos($uri, '://') === false ? 'tcp://' : '') . $uri, PHP_URL_HOST),
+ '[]'
+ );
+
+ $this->app->onOpen($conn->decor);
+
+ $conn->on('data', function ($data) use ($conn) {
+ $this->handleData($data, $conn);
+ });
+ $conn->on('close', function () use ($conn) {
+ $this->handleEnd($conn);
+ });
+ $conn->on('error', function (\Exception $e) use ($conn) {
+ $this->handleError($e, $conn);
+ });
+ }
+
+ /**
+ * Data has been received from React
+ * @param string $data
+ * @param \React\Socket\ConnectionInterface $conn
+ */
+ public function handleData($data, $conn) {
+ try {
+ $this->app->onMessage($conn->decor, $data);
+ } catch (\Exception $e) {
+ $this->handleError($e, $conn);
+ }
+ }
+
+ /**
+ * A connection has been closed by React
+ * @param \React\Socket\ConnectionInterface $conn
+ */
+ public function handleEnd($conn) {
+ try {
+ $this->app->onClose($conn->decor);
+ } catch (\Exception $e) {
+ $this->handleError($e, $conn);
+ }
+
+ unset($conn->decor);
+ }
+
+ /**
+ * An error has occurred, let the listening application know
+ * @param \Exception $e
+ * @param \React\Socket\ConnectionInterface $conn
+ */
+ public function handleError(\Exception $e, $conn) {
+ $this->app->onError($conn->decor, $e);
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Server/IpBlackList.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Server/IpBlackList.php
new file mode 100644
index 0000000..9342254
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Server/IpBlackList.php
@@ -0,0 +1,111 @@
+<?php
+namespace Ratchet\Server;
+use Ratchet\MessageComponentInterface;
+use Ratchet\ConnectionInterface;
+
+class IpBlackList implements MessageComponentInterface {
+ /**
+ * @var array
+ */
+ protected $_blacklist = array();
+
+ /**
+ * @var \Ratchet\MessageComponentInterface
+ */
+ protected $_decorating;
+
+ /**
+ * @param \Ratchet\MessageComponentInterface $component
+ */
+ public function __construct(MessageComponentInterface $component) {
+ $this->_decorating = $component;
+ }
+
+ /**
+ * Add an address to the blacklist that will not be allowed to connect to your application
+ * @param string $ip IP address to block from connecting to your application
+ * @return IpBlackList
+ */
+ public function blockAddress($ip) {
+ $this->_blacklist[$ip] = true;
+
+ return $this;
+ }
+
+ /**
+ * Unblock an address so they can access your application again
+ * @param string $ip IP address to unblock from connecting to your application
+ * @return IpBlackList
+ */
+ public function unblockAddress($ip) {
+ if (isset($this->_blacklist[$this->filterAddress($ip)])) {
+ unset($this->_blacklist[$this->filterAddress($ip)]);
+ }
+
+ return $this;
+ }
+
+ /**
+ * @param string $address
+ * @return bool
+ */
+ public function isBlocked($address) {
+ return (isset($this->_blacklist[$this->filterAddress($address)]));
+ }
+
+ /**
+ * Get an array of all the addresses blocked
+ * @return array
+ */
+ public function getBlockedAddresses() {
+ return array_keys($this->_blacklist);
+ }
+
+ /**
+ * @param string $address
+ * @return string
+ */
+ public function filterAddress($address) {
+ if (strstr($address, ':') && substr_count($address, '.') == 3) {
+ list($address, $port) = explode(':', $address);
+ }
+
+ return $address;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ function onOpen(ConnectionInterface $conn) {
+ if ($this->isBlocked($conn->remoteAddress)) {
+ return $conn->close();
+ }
+
+ return $this->_decorating->onOpen($conn);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ function onMessage(ConnectionInterface $from, $msg) {
+ return $this->_decorating->onMessage($from, $msg);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ function onClose(ConnectionInterface $conn) {
+ if (!$this->isBlocked($conn->remoteAddress)) {
+ $this->_decorating->onClose($conn);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ function onError(ConnectionInterface $conn, \Exception $e) {
+ if (!$this->isBlocked($conn->remoteAddress)) {
+ $this->_decorating->onError($conn, $e);
+ }
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Serialize/HandlerInterface.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Serialize/HandlerInterface.php
new file mode 100644
index 0000000..b83635f
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Serialize/HandlerInterface.php
@@ -0,0 +1,16 @@
+<?php
+namespace Ratchet\Session\Serialize;
+
+interface HandlerInterface {
+ /**
+ * @param array
+ * @return string
+ */
+ function serialize(array $data);
+
+ /**
+ * @param string
+ * @return array
+ */
+ function unserialize($raw);
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Serialize/PhpBinaryHandler.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Serialize/PhpBinaryHandler.php
new file mode 100644
index 0000000..ba80551
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Serialize/PhpBinaryHandler.php
@@ -0,0 +1,33 @@
+<?php
+namespace Ratchet\Session\Serialize;
+
+class PhpBinaryHandler implements HandlerInterface {
+ /**
+ * {@inheritdoc}
+ */
+ function serialize(array $data) {
+ throw new \RuntimeException("Serialize PhpHandler:serialize code not written yet, write me!");
+ }
+
+ /**
+ * {@inheritdoc}
+ * @link http://ca2.php.net/manual/en/function.session-decode.php#108037 Code from this comment on php.net
+ */
+ public function unserialize($raw) {
+ $returnData = array();
+ $offset = 0;
+
+ while ($offset < strlen($raw)) {
+ $num = ord($raw[$offset]);
+ $offset += 1;
+ $varname = substr($raw, $offset, $num);
+ $offset += $num;
+ $data = unserialize(substr($raw, $offset));
+
+ $returnData[$varname] = $data;
+ $offset += strlen(serialize($data));
+ }
+
+ return $returnData;
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Serialize/PhpHandler.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Serialize/PhpHandler.php
new file mode 100644
index 0000000..b1df356
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Serialize/PhpHandler.php
@@ -0,0 +1,49 @@
+<?php
+namespace Ratchet\Session\Serialize;
+
+class PhpHandler implements HandlerInterface {
+ /**
+ * Simply reverse behaviour of unserialize method.
+ * {@inheritdoc}
+ */
+ function serialize(array $data) {
+ $preSerialized = array();
+ $serialized = '';
+
+ if (count($data)) {
+ foreach ($data as $bucket => $bucketData) {
+ $preSerialized[] = $bucket . '|' . serialize($bucketData);
+ }
+ $serialized = implode('', $preSerialized);
+ }
+
+ return $serialized;
+ }
+
+ /**
+ * {@inheritdoc}
+ * @link http://ca2.php.net/manual/en/function.session-decode.php#108037 Code from this comment on php.net
+ * @throws \UnexpectedValueException If there is a problem parsing the data
+ */
+ public function unserialize($raw) {
+ $returnData = array();
+ $offset = 0;
+
+ while ($offset < strlen($raw)) {
+ if (!strstr(substr($raw, $offset), "|")) {
+ throw new \UnexpectedValueException("invalid data, remaining: " . substr($raw, $offset));
+ }
+
+ $pos = strpos($raw, "|", $offset);
+ $num = $pos - $offset;
+ $varname = substr($raw, $offset, $num);
+ $offset += $num + 1;
+ $data = unserialize(substr($raw, $offset));
+
+ $returnData[$varname] = $data;
+ $offset += strlen(serialize($data));
+ }
+
+ return $returnData;
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Session/SessionProvider.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Session/SessionProvider.php
new file mode 100644
index 0000000..44276c5
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Session/SessionProvider.php
@@ -0,0 +1,243 @@
+<?php
+namespace Ratchet\Session;
+use Ratchet\ConnectionInterface;
+use Ratchet\Http\HttpServerInterface;
+use Psr\Http\Message\RequestInterface;
+use Ratchet\Session\Storage\VirtualSessionStorage;
+use Ratchet\Session\Serialize\HandlerInterface;
+use Symfony\Component\HttpFoundation\Session\Session;
+use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler;
+
+/**
+ * This component will allow access to session data from your website for each user connected
+ * Symfony HttpFoundation is required for this component to work
+ * Your website must also use Symfony HttpFoundation Sessions to read your sites session data
+ * If your are not using at least PHP 5.4 you must include a SessionHandlerInterface stub (is included in Symfony HttpFoundation, loaded w/ composer)
+ */
+class SessionProvider implements HttpServerInterface {
+ /**
+ * @var \Ratchet\MessageComponentInterface
+ */
+ protected $_app;
+
+ /**
+ * Selected handler storage assigned by the developer
+ * @var \SessionHandlerInterface
+ */
+ protected $_handler;
+
+ /**
+ * Null storage handler if no previous session was found
+ * @var \SessionHandlerInterface
+ */
+ protected $_null;
+
+ /**
+ * @var \Ratchet\Session\Serialize\HandlerInterface
+ */
+ protected $_serializer;
+
+ /**
+ * @param \Ratchet\Http\HttpServerInterface $app
+ * @param \SessionHandlerInterface $handler
+ * @param array $options
+ * @param \Ratchet\Session\Serialize\HandlerInterface $serializer
+ * @throws \RuntimeException
+ */
+ public function __construct(HttpServerInterface $app, \SessionHandlerInterface $handler, array $options = array(), HandlerInterface $serializer = null) {
+ $this->_app = $app;
+ $this->_handler = $handler;
+ $this->_null = new NullSessionHandler;
+
+ ini_set('session.auto_start', 0);
+ ini_set('session.cache_limiter', '');
+ ini_set('session.use_cookies', 0);
+
+ $this->setOptions($options);
+
+ if (null === $serializer) {
+ $serialClass = __NAMESPACE__ . "\\Serialize\\{$this->toClassCase(ini_get('session.serialize_handler'))}Handler"; // awesome/terrible hack, eh?
+ if (!class_exists($serialClass)) {
+ throw new \RuntimeException('Unable to parse session serialize handler');
+ }
+
+ $serializer = new $serialClass;
+ }
+
+ $this->_serializer = $serializer;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) {
+ $sessionName = ini_get('session.name');
+
+ $id = array_reduce($request->getHeader('Cookie'), function($accumulator, $cookie) use ($sessionName) {
+ if ($accumulator) {
+ return $accumulator;
+ }
+
+ $crumbs = $this->parseCookie($cookie);
+
+ return isset($crumbs['cookies'][$sessionName]) ? $crumbs['cookies'][$sessionName] : false;
+ }, false);
+
+ if (null === $request || false === $id) {
+ $saveHandler = $this->_null;
+ $id = '';
+ } else {
+ $saveHandler = $this->_handler;
+ }
+
+ $conn->Session = new Session(new VirtualSessionStorage($saveHandler, $id, $this->_serializer));
+
+ if (ini_get('session.auto_start')) {
+ $conn->Session->start();
+ }
+
+ return $this->_app->onOpen($conn, $request);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ function onMessage(ConnectionInterface $from, $msg) {
+ return $this->_app->onMessage($from, $msg);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ function onClose(ConnectionInterface $conn) {
+ // "close" session for Connection
+
+ return $this->_app->onClose($conn);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ function onError(ConnectionInterface $conn, \Exception $e) {
+ return $this->_app->onError($conn, $e);
+ }
+
+ /**
+ * Set all the php session. ini options
+ * © Symfony
+ * @param array $options
+ * @return array
+ */
+ protected function setOptions(array $options) {
+ $all = array(
+ 'auto_start', 'cache_limiter', 'cookie_domain', 'cookie_httponly',
+ 'cookie_lifetime', 'cookie_path', 'cookie_secure',
+ 'entropy_file', 'entropy_length', 'gc_divisor',
+ 'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character',
+ 'hash_function', 'name', 'referer_check',
+ 'serialize_handler', 'use_cookies',
+ 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled',
+ 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name',
+ 'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags'
+ );
+
+ foreach ($all as $key) {
+ if (!array_key_exists($key, $options)) {
+ $options[$key] = ini_get("session.{$key}");
+ } else {
+ ini_set("session.{$key}", $options[$key]);
+ }
+ }
+
+ return $options;
+ }
+
+ /**
+ * @param string $langDef Input to convert
+ * @return string
+ */
+ protected function toClassCase($langDef) {
+ return str_replace(' ', '', ucwords(str_replace('_', ' ', $langDef)));
+ }
+
+ /**
+ * Taken from Guzzle3
+ */
+ private static $cookieParts = array(
+ 'domain' => 'Domain',
+ 'path' => 'Path',
+ 'max_age' => 'Max-Age',
+ 'expires' => 'Expires',
+ 'version' => 'Version',
+ 'secure' => 'Secure',
+ 'port' => 'Port',
+ 'discard' => 'Discard',
+ 'comment' => 'Comment',
+ 'comment_url' => 'Comment-Url',
+ 'http_only' => 'HttpOnly'
+ );
+
+ /**
+ * Taken from Guzzle3
+ */
+ private function parseCookie($cookie, $host = null, $path = null, $decode = false) {
+ // Explode the cookie string using a series of semicolons
+ $pieces = array_filter(array_map('trim', explode(';', $cookie)));
+
+ // The name of the cookie (first kvp) must include an equal sign.
+ if (empty($pieces) || !strpos($pieces[0], '=')) {
+ return false;
+ }
+
+ // Create the default return array
+ $data = array_merge(array_fill_keys(array_keys(self::$cookieParts), null), array(
+ 'cookies' => array(),
+ 'data' => array(),
+ 'path' => $path ?: '/',
+ 'http_only' => false,
+ 'discard' => false,
+ 'domain' => $host
+ ));
+ $foundNonCookies = 0;
+
+ // Add the cookie pieces into the parsed data array
+ foreach ($pieces as $part) {
+
+ $cookieParts = explode('=', $part, 2);
+ $key = trim($cookieParts[0]);
+
+ if (count($cookieParts) == 1) {
+ // Can be a single value (e.g. secure, httpOnly)
+ $value = true;
+ } else {
+ // Be sure to strip wrapping quotes
+ $value = trim($cookieParts[1], " \n\r\t\0\x0B\"");
+ if ($decode) {
+ $value = urldecode($value);
+ }
+ }
+
+ // Only check for non-cookies when cookies have been found
+ if (!empty($data['cookies'])) {
+ foreach (self::$cookieParts as $mapValue => $search) {
+ if (!strcasecmp($search, $key)) {
+ $data[$mapValue] = $mapValue == 'port' ? array_map('trim', explode(',', $value)) : $value;
+ $foundNonCookies++;
+ continue 2;
+ }
+ }
+ }
+
+ // If cookies have not yet been retrieved, or this value was not found in the pieces array, treat it as a
+ // cookie. IF non-cookies have been parsed, then this isn't a cookie, it's cookie data. Cookies then data.
+ $data[$foundNonCookies ? 'data' : 'cookies'][$key] = $value;
+ }
+
+ // Calculate the expires date
+ if (!$data['expires'] && $data['max_age']) {
+ $data['expires'] = time() + (int) $data['max_age'];
+ }
+
+ return $data;
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Storage/Proxy/VirtualProxy.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Storage/Proxy/VirtualProxy.php
new file mode 100644
index 0000000..b478d03
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Storage/Proxy/VirtualProxy.php
@@ -0,0 +1,54 @@
+<?php
+namespace Ratchet\Session\Storage\Proxy;
+use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
+
+class VirtualProxy extends SessionHandlerProxy {
+ /**
+ * @var string
+ */
+ protected $_sessionId;
+
+ /**
+ * @var string
+ */
+ protected $_sessionName;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct(\SessionHandlerInterface $handler) {
+ parent::__construct($handler);
+
+ $this->saveHandlerName = 'user';
+ $this->_sessionName = ini_get('session.name');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getId() {
+ return $this->_sessionId;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setId($id) {
+ $this->_sessionId = $id;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName() {
+ return $this->_sessionName;
+ }
+
+ /**
+ * DO NOT CALL THIS METHOD
+ * @internal
+ */
+ public function setName($name) {
+ throw new \RuntimeException("Can not change session name in VirtualProxy");
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Storage/VirtualSessionStorage.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Storage/VirtualSessionStorage.php
new file mode 100644
index 0000000..daa10bb
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Session/Storage/VirtualSessionStorage.php
@@ -0,0 +1,88 @@
+<?php
+namespace Ratchet\Session\Storage;
+use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
+use Ratchet\Session\Storage\Proxy\VirtualProxy;
+use Ratchet\Session\Serialize\HandlerInterface;
+
+class VirtualSessionStorage extends NativeSessionStorage {
+ /**
+ * @var \Ratchet\Session\Serialize\HandlerInterface
+ */
+ protected $_serializer;
+
+ /**
+ * @param \SessionHandlerInterface $handler
+ * @param string $sessionId The ID of the session to retrieve
+ * @param \Ratchet\Session\Serialize\HandlerInterface $serializer
+ */
+ public function __construct(\SessionHandlerInterface $handler, $sessionId, HandlerInterface $serializer) {
+ $this->setSaveHandler($handler);
+ $this->saveHandler->setId($sessionId);
+ $this->_serializer = $serializer;
+ $this->setMetadataBag(null);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function start() {
+ if ($this->started && !$this->closed) {
+ return true;
+ }
+
+ // You have to call Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler::open() to use
+ // pdo_sqlite (and possible pdo_*) as session storage, if you are using a DSN string instead of a \PDO object
+ // in the constructor. The method arguments are filled with the values, which are also used by the symfony
+ // framework in this case. This must not be the best choice, but it works.
+ $this->saveHandler->open(session_save_path(), session_name());
+
+ $rawData = $this->saveHandler->read($this->saveHandler->getId());
+ $sessionData = $this->_serializer->unserialize($rawData);
+
+ $this->loadSession($sessionData);
+
+ if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
+ $this->saveHandler->setActive(false);
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function regenerate($destroy = false, $lifetime = null) {
+ // .. ?
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function save() {
+ // get the data from the bags?
+ // serialize the data
+ // save the data using the saveHandler
+// $this->saveHandler->write($this->saveHandler->getId(),
+
+ if (!$this->saveHandler->isWrapper() && !$this->getSaveHandler()->isSessionHandlerInterface()) {
+ $this->saveHandler->setActive(false);
+ }
+
+ $this->closed = true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setSaveHandler($saveHandler = null) {
+ if (!($saveHandler instanceof \SessionHandlerInterface)) {
+ throw new \InvalidArgumentException('Handler must be instance of SessionHandlerInterface');
+ }
+
+ if (!($saveHandler instanceof VirtualProxy)) {
+ $saveHandler = new VirtualProxy($saveHandler);
+ }
+
+ $this->saveHandler = $saveHandler;
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/Exception.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/Exception.php
new file mode 100644
index 0000000..6c824da
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/Exception.php
@@ -0,0 +1,5 @@
+<?php
+namespace Ratchet\Wamp;
+
+class Exception extends \Exception {
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/JsonException.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/JsonException.php
new file mode 100644
index 0000000..8f05d28
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/JsonException.php
@@ -0,0 +1,31 @@
+<?php
+namespace Ratchet\Wamp;
+
+class JsonException extends Exception {
+ public function __construct() {
+ $code = json_last_error();
+
+ switch ($code) {
+ case JSON_ERROR_DEPTH:
+ $msg = 'Maximum stack depth exceeded';
+ break;
+ case JSON_ERROR_STATE_MISMATCH:
+ $msg = 'Underflow or the modes mismatch';
+ break;
+ case JSON_ERROR_CTRL_CHAR:
+ $msg = 'Unexpected control character found';
+ break;
+ case JSON_ERROR_SYNTAX:
+ $msg = 'Syntax error, malformed JSON';
+ break;
+ case JSON_ERROR_UTF8:
+ $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
+ break;
+ default:
+ $msg = 'Unknown error';
+ break;
+ }
+
+ parent::__construct($msg, $code);
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/ServerProtocol.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/ServerProtocol.php
new file mode 100644
index 0000000..2d6d799
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/ServerProtocol.php
@@ -0,0 +1,161 @@
+<?php
+namespace Ratchet\Wamp;
+use Ratchet\MessageComponentInterface;
+use Ratchet\WebSocket\WsServerInterface;
+use Ratchet\ConnectionInterface;
+
+/**
+ * WebSocket Application Messaging Protocol
+ *
+ * @link http://wamp.ws/spec
+ * @link https://github.com/oberstet/autobahn-js
+ *
+ * +--------------+----+------------------+
+ * | Message Type | ID | DIRECTION |
+ * |--------------+----+------------------+
+ * | WELCOME | 0 | Server-to-Client |
+ * | PREFIX | 1 | Bi-Directional |
+ * | CALL | 2 | Client-to-Server |
+ * | CALL RESULT | 3 | Server-to-Client |
+ * | CALL ERROR | 4 | Server-to-Client |
+ * | SUBSCRIBE | 5 | Client-to-Server |
+ * | UNSUBSCRIBE | 6 | Client-to-Server |
+ * | PUBLISH | 7 | Client-to-Server |
+ * | EVENT | 8 | Server-to-Client |
+ * +--------------+----+------------------+
+ */
+class ServerProtocol implements MessageComponentInterface, WsServerInterface {
+ const MSG_WELCOME = 0;
+ const MSG_PREFIX = 1;
+ const MSG_CALL = 2;
+ const MSG_CALL_RESULT = 3;
+ const MSG_CALL_ERROR = 4;
+ const MSG_SUBSCRIBE = 5;
+ const MSG_UNSUBSCRIBE = 6;
+ const MSG_PUBLISH = 7;
+ const MSG_EVENT = 8;
+
+ /**
+ * @var WampServerInterface
+ */
+ protected $_decorating;
+
+ /**
+ * @var \SplObjectStorage
+ */
+ protected $connections;
+
+ /**
+ * @param WampServerInterface $serverComponent An class to propagate calls through
+ */
+ public function __construct(WampServerInterface $serverComponent) {
+ $this->_decorating = $serverComponent;
+ $this->connections = new \SplObjectStorage;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getSubProtocols() {
+ if ($this->_decorating instanceof WsServerInterface) {
+ $subs = $this->_decorating->getSubProtocols();
+ $subs[] = 'wamp';
+
+ return $subs;
+ }
+
+ return ['wamp'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onOpen(ConnectionInterface $conn) {
+ $decor = new WampConnection($conn);
+ $this->connections->attach($conn, $decor);
+
+ $this->_decorating->onOpen($decor);
+ }
+
+ /**
+ * {@inheritdoc}
+ * @throws \Ratchet\Wamp\Exception
+ * @throws \Ratchet\Wamp\JsonException
+ */
+ public function onMessage(ConnectionInterface $from, $msg) {
+ $from = $this->connections[$from];
+
+ if (null === ($json = @json_decode($msg, true))) {
+ throw new JsonException;
+ }
+
+ if (!is_array($json) || $json !== array_values($json)) {
+ throw new Exception("Invalid WAMP message format");
+ }
+
+ if (isset($json[1]) && !(is_string($json[1]) || is_numeric($json[1]))) {
+ throw new Exception('Invalid Topic, must be a string');
+ }
+
+ switch ($json[0]) {
+ case static::MSG_PREFIX:
+ $from->WAMP->prefixes[$json[1]] = $json[2];
+ break;
+
+ case static::MSG_CALL:
+ array_shift($json);
+ $callID = array_shift($json);
+ $procURI = array_shift($json);
+
+ if (count($json) == 1 && is_array($json[0])) {
+ $json = $json[0];
+ }
+
+ $this->_decorating->onCall($from, $callID, $from->getUri($procURI), $json);
+ break;
+
+ case static::MSG_SUBSCRIBE:
+ $this->_decorating->onSubscribe($from, $from->getUri($json[1]));
+ break;
+
+ case static::MSG_UNSUBSCRIBE:
+ $this->_decorating->onUnSubscribe($from, $from->getUri($json[1]));
+ break;
+
+ case static::MSG_PUBLISH:
+ $exclude = (array_key_exists(3, $json) ? $json[3] : null);
+ if (!is_array($exclude)) {
+ if (true === (boolean)$exclude) {
+ $exclude = [$from->WAMP->sessionId];
+ } else {
+ $exclude = [];
+ }
+ }
+
+ $eligible = (array_key_exists(4, $json) ? $json[4] : []);
+
+ $this->_decorating->onPublish($from, $from->getUri($json[1]), $json[2], $exclude, $eligible);
+ break;
+
+ default:
+ throw new Exception('Invalid WAMP message type');
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onClose(ConnectionInterface $conn) {
+ $decor = $this->connections[$conn];
+ $this->connections->detach($conn);
+
+ $this->_decorating->onClose($decor);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onError(ConnectionInterface $conn, \Exception $e) {
+ return $this->_decorating->onError($this->connections[$conn], $e);
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/Topic.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/Topic.php
new file mode 100644
index 0000000..bca8f67
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/Topic.php
@@ -0,0 +1,99 @@
+<?php
+namespace Ratchet\Wamp;
+use Ratchet\ConnectionInterface;
+
+/**
+ * A topic/channel containing connections that have subscribed to it
+ */
+class Topic implements \IteratorAggregate, \Countable {
+ private $id;
+
+ private $subscribers;
+
+ /**
+ * @param string $topicId Unique ID for this object
+ */
+ public function __construct($topicId) {
+ $this->id = $topicId;
+ $this->subscribers = new \SplObjectStorage;
+ }
+
+ /**
+ * @return string
+ */
+ public function getId() {
+ return $this->id;
+ }
+
+ public function __toString() {
+ return $this->getId();
+ }
+
+ /**
+ * Send a message to all the connections in this topic
+ * @param string|array $msg Payload to publish
+ * @param array $exclude A list of session IDs the message should be excluded from (blacklist)
+ * @param array $eligible A list of session Ids the message should be send to (whitelist)
+ * @return Topic The same Topic object to chain
+ */
+ public function broadcast($msg, array $exclude = array(), array $eligible = array()) {
+ $useEligible = (bool)count($eligible);
+ foreach ($this->subscribers as $client) {
+ if (in_array($client->WAMP->sessionId, $exclude)) {
+ continue;
+ }
+
+ if ($useEligible && !in_array($client->WAMP->sessionId, $eligible)) {
+ continue;
+ }
+
+ $client->event($this->id, $msg);
+ }
+
+ return $this;
+ }
+
+ /**
+ * @param WampConnection $conn
+ * @return boolean
+ */
+ public function has(ConnectionInterface $conn) {
+ return $this->subscribers->contains($conn);
+ }
+
+ /**
+ * @param WampConnection $conn
+ * @return Topic
+ */
+ public function add(ConnectionInterface $conn) {
+ $this->subscribers->attach($conn);
+
+ return $this;
+ }
+
+ /**
+ * @param WampConnection $conn
+ * @return Topic
+ */
+ public function remove(ConnectionInterface $conn) {
+ if ($this->subscribers->contains($conn)) {
+ $this->subscribers->detach($conn);
+ }
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getIterator() {
+ return $this->subscribers;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function count() {
+ return $this->subscribers->count();
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/TopicManager.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/TopicManager.php
new file mode 100644
index 0000000..dd06ada
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/TopicManager.php
@@ -0,0 +1,125 @@
+<?php
+namespace Ratchet\Wamp;
+use Ratchet\ConnectionInterface;
+use Ratchet\WebSocket\WsServerInterface;
+
+class TopicManager implements WsServerInterface, WampServerInterface {
+ /**
+ * @var WampServerInterface
+ */
+ protected $app;
+
+ /**
+ * @var array
+ */
+ protected $topicLookup = array();
+
+ public function __construct(WampServerInterface $app) {
+ $this->app = $app;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onOpen(ConnectionInterface $conn) {
+ $conn->WAMP->subscriptions = new \SplObjectStorage;
+ $this->app->onOpen($conn);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onCall(ConnectionInterface $conn, $id, $topic, array $params) {
+ $this->app->onCall($conn, $id, $this->getTopic($topic), $params);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onSubscribe(ConnectionInterface $conn, $topic) {
+ $topicObj = $this->getTopic($topic);
+
+ if ($conn->WAMP->subscriptions->contains($topicObj)) {
+ return;
+ }
+
+ $this->topicLookup[$topic]->add($conn);
+ $conn->WAMP->subscriptions->attach($topicObj);
+ $this->app->onSubscribe($conn, $topicObj);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onUnsubscribe(ConnectionInterface $conn, $topic) {
+ $topicObj = $this->getTopic($topic);
+
+ if (!$conn->WAMP->subscriptions->contains($topicObj)) {
+ return;
+ }
+
+ $this->cleanTopic($topicObj, $conn);
+
+ $this->app->onUnsubscribe($conn, $topicObj);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible) {
+ $this->app->onPublish($conn, $this->getTopic($topic), $event, $exclude, $eligible);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onClose(ConnectionInterface $conn) {
+ $this->app->onClose($conn);
+
+ foreach ($this->topicLookup as $topic) {
+ $this->cleanTopic($topic, $conn);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onError(ConnectionInterface $conn, \Exception $e) {
+ $this->app->onError($conn, $e);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getSubProtocols() {
+ if ($this->app instanceof WsServerInterface) {
+ return $this->app->getSubProtocols();
+ }
+
+ return array();
+ }
+
+ /**
+ * @param string
+ * @return Topic
+ */
+ protected function getTopic($topic) {
+ if (!array_key_exists($topic, $this->topicLookup)) {
+ $this->topicLookup[$topic] = new Topic($topic);
+ }
+
+ return $this->topicLookup[$topic];
+ }
+
+ protected function cleanTopic(Topic $topic, ConnectionInterface $conn) {
+ if ($conn->WAMP->subscriptions->contains($topic)) {
+ $conn->WAMP->subscriptions->detach($topic);
+ }
+
+ $this->topicLookup[$topic->getId()]->remove($conn);
+
+ if (0 === $topic->count()) {
+ unset($this->topicLookup[$topic->getId()]);
+ }
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampConnection.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampConnection.php
new file mode 100644
index 0000000..dda1e4e
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampConnection.php
@@ -0,0 +1,115 @@
+<?php
+namespace Ratchet\Wamp;
+use Ratchet\ConnectionInterface;
+use Ratchet\AbstractConnectionDecorator;
+use Ratchet\Wamp\ServerProtocol as WAMP;
+
+/**
+ * A ConnectionInterface object wrapper that is passed to your WAMP application
+ * representing a client. Methods on this Connection are therefore different.
+ * @property \stdClass $WAMP
+ */
+class WampConnection extends AbstractConnectionDecorator {
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct(ConnectionInterface $conn) {
+ parent::__construct($conn);
+
+ $this->WAMP = new \StdClass;
+ $this->WAMP->sessionId = str_replace('.', '', uniqid(mt_rand(), true));
+ $this->WAMP->prefixes = array();
+
+ $this->send(json_encode(array(WAMP::MSG_WELCOME, $this->WAMP->sessionId, 1, \Ratchet\VERSION)));
+ }
+
+ /**
+ * Successfully respond to a call made by the client
+ * @param string $id The unique ID given by the client to respond to
+ * @param array $data an object or array
+ * @return WampConnection
+ */
+ public function callResult($id, $data = array()) {
+ return $this->send(json_encode(array(WAMP::MSG_CALL_RESULT, $id, $data)));
+ }
+
+ /**
+ * Respond with an error to a client call
+ * @param string $id The unique ID given by the client to respond to
+ * @param string $errorUri The URI given to identify the specific error
+ * @param string $desc A developer-oriented description of the error
+ * @param string $details An optional human readable detail message to send back
+ * @return WampConnection
+ */
+ public function callError($id, $errorUri, $desc = '', $details = null) {
+ if ($errorUri instanceof Topic) {
+ $errorUri = (string)$errorUri;
+ }
+
+ $data = array(WAMP::MSG_CALL_ERROR, $id, $errorUri, $desc);
+
+ if (null !== $details) {
+ $data[] = $details;
+ }
+
+ return $this->send(json_encode($data));
+ }
+
+ /**
+ * @param string $topic The topic to broadcast to
+ * @param mixed $msg Data to send with the event. Anything that is json'able
+ * @return WampConnection
+ */
+ public function event($topic, $msg) {
+ return $this->send(json_encode(array(WAMP::MSG_EVENT, (string)$topic, $msg)));
+ }
+
+ /**
+ * @param string $curie
+ * @param string $uri
+ * @return WampConnection
+ */
+ public function prefix($curie, $uri) {
+ $this->WAMP->prefixes[$curie] = (string)$uri;
+
+ return $this->send(json_encode(array(WAMP::MSG_PREFIX, $curie, (string)$uri)));
+ }
+
+ /**
+ * Get the full request URI from the connection object if a prefix has been established for it
+ * @param string $uri
+ * @return string
+ */
+ public function getUri($uri) {
+ $curieSeperator = ':';
+
+ if (preg_match('/http(s*)\:\/\//', $uri) == false) {
+ if (strpos($uri, $curieSeperator) !== false) {
+ list($prefix, $action) = explode($curieSeperator, $uri);
+
+ if(isset($this->WAMP->prefixes[$prefix]) === true){
+ return $this->WAMP->prefixes[$prefix] . '#' . $action;
+ }
+ }
+ }
+
+ return $uri;
+ }
+
+ /**
+ * @internal
+ */
+ public function send($data) {
+ $this->getConnection()->send($data);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function close($opt = null) {
+ $this->getConnection()->close($opt);
+ }
+
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServer.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServer.php
new file mode 100644
index 0000000..5d710aa
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServer.php
@@ -0,0 +1,67 @@
+<?php
+namespace Ratchet\Wamp;
+use Ratchet\MessageComponentInterface;
+use Ratchet\WebSocket\WsServerInterface;
+use Ratchet\ConnectionInterface;
+
+/**
+ * Enable support for the official WAMP sub-protocol in your application
+ * WAMP allows for Pub/Sub and RPC
+ * @link http://wamp.ws The WAMP specification
+ * @link https://github.com/oberstet/autobahn-js Souce for client side library
+ * @link http://autobahn.s3.amazonaws.com/js/autobahn.min.js Minified client side library
+ */
+class WampServer implements MessageComponentInterface, WsServerInterface {
+ /**
+ * @var ServerProtocol
+ */
+ protected $wampProtocol;
+
+ /**
+ * This class just makes it 1 step easier to use Topic objects in WAMP
+ * If you're looking at the source code, look in the __construct of this
+ * class and use that to make your application instead of using this
+ */
+ public function __construct(WampServerInterface $app) {
+ $this->wampProtocol = new ServerProtocol(new TopicManager($app));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onOpen(ConnectionInterface $conn) {
+ $this->wampProtocol->onOpen($conn);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onMessage(ConnectionInterface $conn, $msg) {
+ try {
+ $this->wampProtocol->onMessage($conn, $msg);
+ } catch (Exception $we) {
+ $conn->close(1007);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onClose(ConnectionInterface $conn) {
+ $this->wampProtocol->onClose($conn);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onError(ConnectionInterface $conn, \Exception $e) {
+ $this->wampProtocol->onError($conn, $e);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getSubProtocols() {
+ return $this->wampProtocol->getSubProtocols();
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServerInterface.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServerInterface.php
new file mode 100644
index 0000000..15c521d
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServerInterface.php
@@ -0,0 +1,43 @@
+<?php
+namespace Ratchet\Wamp;
+use Ratchet\ComponentInterface;
+use Ratchet\ConnectionInterface;
+
+/**
+ * An extension of Ratchet\ComponentInterface to server a WAMP application
+ * onMessage is replaced by various types of messages for this protocol (pub/sub or rpc)
+ */
+interface WampServerInterface extends ComponentInterface {
+ /**
+ * An RPC call has been received
+ * @param \Ratchet\ConnectionInterface $conn
+ * @param string $id The unique ID of the RPC, required to respond to
+ * @param string|Topic $topic The topic to execute the call against
+ * @param array $params Call parameters received from the client
+ */
+ function onCall(ConnectionInterface $conn, $id, $topic, array $params);
+
+ /**
+ * A request to subscribe to a topic has been made
+ * @param \Ratchet\ConnectionInterface $conn
+ * @param string|Topic $topic The topic to subscribe to
+ */
+ function onSubscribe(ConnectionInterface $conn, $topic);
+
+ /**
+ * A request to unsubscribe from a topic has been made
+ * @param \Ratchet\ConnectionInterface $conn
+ * @param string|Topic $topic The topic to unsubscribe from
+ */
+ function onUnSubscribe(ConnectionInterface $conn, $topic);
+
+ /**
+ * A client is attempting to publish content to a subscribed connections on a URI
+ * @param \Ratchet\ConnectionInterface $conn
+ * @param string|Topic $topic The topic the user has attempted to publish to
+ * @param string $event Payload of the publish
+ * @param array $exclude A list of session IDs the message should be excluded from (blacklist)
+ * @param array $eligible A list of session Ids the message should be send to (whitelist)
+ */
+ function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible);
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/ConnContext.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/ConnContext.php
new file mode 100644
index 0000000..2eba782
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/ConnContext.php
@@ -0,0 +1,20 @@
+<?php
+namespace Ratchet\WebSocket;
+use Ratchet\RFC6455\Messaging\MessageBuffer;
+
+class ConnContext {
+ /**
+ * @var \Ratchet\WebSocket\WsConnection
+ */
+ public $connection;
+
+ /**
+ * @var \Ratchet\RFC6455\Messaging\MessageBuffer;
+ */
+ public $buffer;
+
+ public function __construct(WsConnection $conn, MessageBuffer $buffer) {
+ $this->connection = $conn;
+ $this->buffer = $buffer;
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/MessageCallableInterface.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/MessageCallableInterface.php
new file mode 100644
index 0000000..b5c094e
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/MessageCallableInterface.php
@@ -0,0 +1,8 @@
+<?php
+namespace Ratchet\WebSocket;
+use Ratchet\ConnectionInterface;
+use Ratchet\RFC6455\Messaging\MessageInterface;
+
+interface MessageCallableInterface {
+ public function onMessage(ConnectionInterface $conn, MessageInterface $msg);
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/MessageComponentInterface.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/MessageComponentInterface.php
new file mode 100644
index 0000000..fccd4e6
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/MessageComponentInterface.php
@@ -0,0 +1,6 @@
+<?php
+namespace Ratchet\WebSocket;
+use Ratchet\ComponentInterface;
+
+interface MessageComponentInterface extends ComponentInterface, MessageCallableInterface {
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/WsConnection.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/WsConnection.php
new file mode 100644
index 0000000..d2d04ef
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/WsConnection.php
@@ -0,0 +1,45 @@
+<?php
+namespace Ratchet\WebSocket;
+use Ratchet\AbstractConnectionDecorator;
+use Ratchet\RFC6455\Messaging\DataInterface;
+use Ratchet\RFC6455\Messaging\Frame;
+
+/**
+ * {@inheritdoc}
+ * @property \StdClass $WebSocket
+ */
+class WsConnection extends AbstractConnectionDecorator {
+ /**
+ * {@inheritdoc}
+ */
+ public function send($msg) {
+ if (!$this->WebSocket->closing) {
+ if (!($msg instanceof DataInterface)) {
+ $msg = new Frame($msg);
+ }
+
+ $this->getConnection()->send($msg->getContents());
+ }
+
+ return $this;
+ }
+
+ /**
+ * @param int|\Ratchet\RFC6455\Messaging\DataInterface
+ */
+ public function close($code = 1000) {
+ if ($this->WebSocket->closing) {
+ return;
+ }
+
+ if ($code instanceof DataInterface) {
+ $this->send($code);
+ } else {
+ $this->send(new Frame(pack('n', $code), true, Frame::OP_CLOSE));
+ }
+
+ $this->getConnection()->close();
+
+ $this->WebSocket->closing = true;
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/WsServer.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/WsServer.php
new file mode 100644
index 0000000..8030604
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/WsServer.php
@@ -0,0 +1,225 @@
+<?php
+namespace Ratchet\WebSocket;
+use Ratchet\ComponentInterface;
+use Ratchet\ConnectionInterface;
+use Ratchet\MessageComponentInterface as DataComponentInterface;
+use Ratchet\Http\HttpServerInterface;
+use Ratchet\Http\CloseResponseTrait;
+use Psr\Http\Message\RequestInterface;
+use Ratchet\RFC6455\Messaging\MessageInterface;
+use Ratchet\RFC6455\Messaging\FrameInterface;
+use Ratchet\RFC6455\Messaging\Frame;
+use Ratchet\RFC6455\Messaging\MessageBuffer;
+use Ratchet\RFC6455\Messaging\CloseFrameChecker;
+use Ratchet\RFC6455\Handshake\ServerNegotiator;
+use Ratchet\RFC6455\Handshake\RequestVerifier;
+use React\EventLoop\LoopInterface;
+use GuzzleHttp\Psr7 as gPsr;
+
+/**
+ * The adapter to handle WebSocket requests/responses
+ * This is a mediator between the Server and your application to handle real-time messaging through a web browser
+ * @link http://ca.php.net/manual/en/ref.http.php
+ * @link http://dev.w3.org/html5/websockets/
+ */
+class WsServer implements HttpServerInterface {
+ use CloseResponseTrait;
+
+ /**
+ * Decorated component
+ * @var \Ratchet\ComponentInterface
+ */
+ private $delegate;
+
+ /**
+ * @var \SplObjectStorage
+ */
+ protected $connections;
+
+ /**
+ * @var \Ratchet\RFC6455\Messaging\CloseFrameChecker
+ */
+ private $closeFrameChecker;
+
+ /**
+ * @var \Ratchet\RFC6455\Handshake\ServerNegotiator
+ */
+ private $handshakeNegotiator;
+
+ /**
+ * @var \Closure
+ */
+ private $ueFlowFactory;
+
+ /**
+ * @var \Closure
+ */
+ private $pongReceiver;
+
+ /**
+ * @var \Closure
+ */
+ private $msgCb;
+
+ /**
+ * @param \Ratchet\WebSocket\MessageComponentInterface|\Ratchet\MessageComponentInterface $component Your application to run with WebSockets
+ * @note If you want to enable sub-protocols have your component implement WsServerInterface as well
+ */
+ public function __construct(ComponentInterface $component) {
+ if ($component instanceof MessageComponentInterface) {
+ $this->msgCb = function(ConnectionInterface $conn, MessageInterface $msg) {
+ $this->delegate->onMessage($conn, $msg);
+ };
+ } elseif ($component instanceof DataComponentInterface) {
+ $this->msgCb = function(ConnectionInterface $conn, MessageInterface $msg) {
+ $this->delegate->onMessage($conn, $msg->getPayload());
+ };
+ } else {
+ throw new \UnexpectedValueException('Expected instance of \Ratchet\WebSocket\MessageComponentInterface or \Ratchet\MessageComponentInterface');
+ }
+
+ if (bin2hex('✓') !== 'e29c93') {
+ throw new \DomainException('Bad encoding, unicode character ✓ did not match expected value. Ensure charset UTF-8 and check ini val mbstring.func_autoload');
+ }
+
+ $this->delegate = $component;
+ $this->connections = new \SplObjectStorage;
+
+ $this->closeFrameChecker = new CloseFrameChecker;
+ $this->handshakeNegotiator = new ServerNegotiator(new RequestVerifier);
+ $this->handshakeNegotiator->setStrictSubProtocolCheck(true);
+
+ if ($component instanceof WsServerInterface) {
+ $this->handshakeNegotiator->setSupportedSubProtocols($component->getSubProtocols());
+ }
+
+ $this->pongReceiver = function() {};
+
+ $reusableUnderflowException = new \UnderflowException;
+ $this->ueFlowFactory = function() use ($reusableUnderflowException) {
+ return $reusableUnderflowException;
+ };
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) {
+ if (null === $request) {
+ throw new \UnexpectedValueException('$request can not be null');
+ }
+
+ $conn->httpRequest = $request;
+
+ $conn->WebSocket = new \StdClass;
+ $conn->WebSocket->closing = false;
+
+ $response = $this->handshakeNegotiator->handshake($request)->withHeader('X-Powered-By', \Ratchet\VERSION);
+
+ $conn->send(gPsr\str($response));
+
+ if (101 !== $response->getStatusCode()) {
+ return $conn->close();
+ }
+
+ $wsConn = new WsConnection($conn);
+
+ $streamer = new MessageBuffer(
+ $this->closeFrameChecker,
+ function(MessageInterface $msg) use ($wsConn) {
+ $cb = $this->msgCb;
+ $cb($wsConn, $msg);
+ },
+ function(FrameInterface $frame) use ($wsConn) {
+ $this->onControlFrame($frame, $wsConn);
+ },
+ true,
+ $this->ueFlowFactory
+ );
+
+ $this->connections->attach($conn, new ConnContext($wsConn, $streamer));
+
+ return $this->delegate->onOpen($wsConn);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onMessage(ConnectionInterface $from, $msg) {
+ if ($from->WebSocket->closing) {
+ return;
+ }
+
+ $this->connections[$from]->buffer->onData($msg);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onClose(ConnectionInterface $conn) {
+ if ($this->connections->contains($conn)) {
+ $context = $this->connections[$conn];
+ $this->connections->detach($conn);
+
+ $this->delegate->onClose($context->connection);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function onError(ConnectionInterface $conn, \Exception $e) {
+ if ($this->connections->contains($conn)) {
+ $this->delegate->onError($this->connections[$conn]->connection, $e);
+ } else {
+ $conn->close();
+ }
+ }
+
+ public function onControlFrame(FrameInterface $frame, WsConnection $conn) {
+ switch ($frame->getOpCode()) {
+ case Frame::OP_CLOSE:
+ $conn->close($frame);
+ break;
+ case Frame::OP_PING:
+ $conn->send(new Frame($frame->getPayload(), true, Frame::OP_PONG));
+ break;
+ case Frame::OP_PONG:
+ $pongReceiver = $this->pongReceiver;
+ $pongReceiver($frame, $conn);
+ break;
+ }
+ }
+
+ public function setStrictSubProtocolCheck($enable) {
+ $this->handshakeNegotiator->setStrictSubProtocolCheck($enable);
+ }
+
+ public function enableKeepAlive(LoopInterface $loop, $interval = 30) {
+ $lastPing = new Frame(uniqid(), true, Frame::OP_PING);
+ $pingedConnections = new \SplObjectStorage;
+ $splClearer = new \SplObjectStorage;
+
+ $this->pongReceiver = function(FrameInterface $frame, $wsConn) use ($pingedConnections, &$lastPing) {
+ if ($frame->getPayload() === $lastPing->getPayload()) {
+ $pingedConnections->detach($wsConn);
+ }
+ };
+
+ $loop->addPeriodicTimer((int)$interval, function() use ($pingedConnections, &$lastPing, $splClearer) {
+ foreach ($pingedConnections as $wsConn) {
+ $wsConn->close();
+ }
+ $pingedConnections->removeAllExcept($splClearer);
+
+ $lastPing = new Frame(uniqid(), true, Frame::OP_PING);
+
+ foreach ($this->connections as $key => $conn) {
+ $wsConn = $this->connections[$conn]->connection;
+
+ $wsConn->send($lastPing);
+ $pingedConnections->attach($wsConn);
+ }
+ });
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/WsServerInterface.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/WsServerInterface.php
new file mode 100644
index 0000000..15d1f7b
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/WebSocket/WsServerInterface.php
@@ -0,0 +1,14 @@
+<?php
+namespace Ratchet\WebSocket;
+
+/**
+ * WebSocket Server Interface
+ */
+interface WsServerInterface {
+ /**
+ * If any component in a stack supports a WebSocket sub-protocol return each supported in an array
+ * @return array
+ * @todo This method may be removed in future version (note that will not break code, just make some code obsolete)
+ */
+ function getSubProtocols();
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/autobahn/bin/fuzzingserver.php b/assets/php/vendor/cboden/ratchet/tests/autobahn/bin/fuzzingserver.php
new file mode 100644
index 0000000..66d3704
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/autobahn/bin/fuzzingserver.php
@@ -0,0 +1,36 @@
+<?php
+use Ratchet\ConnectionInterface;
+
+ require dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+
+class BinaryEcho implements \Ratchet\WebSocket\MessageComponentInterface {
+ public function onMessage(ConnectionInterface $from, \Ratchet\RFC6455\Messaging\MessageInterface $msg) {
+ $from->send($msg);
+ }
+
+ public function onOpen(ConnectionInterface $conn) {
+ }
+
+ public function onClose(ConnectionInterface $conn) {
+ }
+
+ public function onError(ConnectionInterface $conn, \Exception $e) {
+ }
+}
+
+ $port = $argc > 1 ? $argv[1] : 8000;
+ $impl = sprintf('React\EventLoop\%sLoop', $argc > 2 ? $argv[2] : 'StreamSelect');
+
+ $loop = new $impl;
+ $sock = new React\Socket\Server('0.0.0.0:' . $port, $loop);
+
+ $wsServer = new Ratchet\WebSocket\WsServer(new BinaryEcho);
+ // This is enabled to test https://github.com/ratchetphp/Ratchet/issues/430
+ // The time is left at 10 minutes so that it will not try to every ping anything
+ // This causes the Ratchet server to crash on test 2.7
+ $wsServer->enableKeepAlive($loop, 600);
+
+ $app = new Ratchet\Http\HttpServer($wsServer);
+
+ $server = new Ratchet\Server\IoServer($app, $sock, $loop);
+ $server->run();
diff --git a/assets/php/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-all.json b/assets/php/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-all.json
new file mode 100644
index 0000000..0494cf3
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-all.json
@@ -0,0 +1,15 @@
+{
+ "options": {"failByDrop": false}
+ , "outdir": "reports/ab"
+
+ , "servers": [
+ {"agent": "Ratchet/0.4 libevent", "url": "ws://localhost:8001", "options": {"version": 18}}
+ , {"agent": "Ratchet/0.4 libev", "url": "ws://localhost:8004", "options": {"version": 18}}
+ , {"agent": "Ratchet/0.4 streams", "url": "ws://localhost:8002", "options": {"version": 18}}
+ , {"agent": "AutobahnTestSuite/0.5.9", "url": "ws://localhost:8000", "options": {"version": 18}}
+ ]
+
+ , "cases": ["*"]
+ , "exclude-cases": []
+ , "exclude-agent-cases": {}
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-profile.json b/assets/php/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-profile.json
new file mode 100644
index 0000000..e81a9fd
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-profile.json
@@ -0,0 +1,12 @@
+{
+ "options": {"failByDrop": false}
+ , "outdir": "reports/profile"
+
+ , "servers": [
+ {"agent": "Ratchet", "url": "ws://localhost:8000", "options": {"version": 18}}
+ ]
+
+ , "cases": ["9.7.4"]
+ , "exclude-cases": ["1.2.*", "2.3", "2.4", "2.6", "9.2.*", "9.4.*", "9.6.*", "9.8.*"]
+ , "exclude-agent-cases": {}
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-quick.json b/assets/php/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-quick.json
new file mode 100644
index 0000000..c92e805
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/autobahn/fuzzingclient-quick.json
@@ -0,0 +1,12 @@
+{
+ "options": {"failByDrop": false}
+ , "outdir": "reports/rfc"
+
+ , "servers": [
+ {"agent": "Ratchet", "url": "ws://localhost:8000", "options": {"version": 18}}
+ ]
+
+ , "cases": ["*"]
+ , "exclude-cases": []
+ , "exclude-agent-cases": {}
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/bootstrap.php b/assets/php/vendor/cboden/ratchet/tests/bootstrap.php
new file mode 100644
index 0000000..40791ba
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/bootstrap.php
@@ -0,0 +1,4 @@
+<?php
+
+ $loader = require __DIR__ . '/../vendor/autoload.php';
+ $loader->addPsr4('Ratchet\\', __DIR__ . '/helpers/Ratchet');
diff --git a/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/AbstractMessageComponentTestCase.php b/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/AbstractMessageComponentTestCase.php
new file mode 100644
index 0000000..8c298e5
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/AbstractMessageComponentTestCase.php
@@ -0,0 +1,50 @@
+<?php
+namespace Ratchet;
+
+abstract class AbstractMessageComponentTestCase extends \PHPUnit_Framework_TestCase {
+ protected $_app;
+ protected $_serv;
+ protected $_conn;
+
+ abstract public function getConnectionClassString();
+ abstract public function getDecoratorClassString();
+ abstract public function getComponentClassString();
+
+ public function setUp() {
+ $this->_app = $this->getMock($this->getComponentClassString());
+ $decorator = $this->getDecoratorClassString();
+ $this->_serv = new $decorator($this->_app);
+ $this->_conn = $this->getMock('\Ratchet\ConnectionInterface');
+
+ $this->doOpen($this->_conn);
+ }
+
+ protected function doOpen($conn) {
+ $this->_serv->onOpen($conn);
+ }
+
+ public function isExpectedConnection() {
+ return new \PHPUnit_Framework_Constraint_IsInstanceOf($this->getConnectionClassString());
+ }
+
+ public function testOpen() {
+ $this->_app->expects($this->once())->method('onOpen')->with($this->isExpectedConnection());
+ $this->doOpen($this->getMock('\Ratchet\ConnectionInterface'));
+ }
+
+ public function testOnClose() {
+ $this->_app->expects($this->once())->method('onClose')->with($this->isExpectedConnection());
+ $this->_serv->onClose($this->_conn);
+ }
+
+ public function testOnError() {
+ $e = new \Exception('Whoops!');
+ $this->_app->expects($this->once())->method('onError')->with($this->isExpectedConnection(), $e);
+ $this->_serv->onError($this->_conn, $e);
+ }
+
+ public function passthroughMessageTest($value) {
+ $this->_app->expects($this->once())->method('onMessage')->with($this->isExpectedConnection(), $value);
+ $this->_serv->onMessage($this->_conn, $value);
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/Component.php b/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/Component.php
new file mode 100644
index 0000000..e152988
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/Component.php
@@ -0,0 +1,35 @@
+<?php
+namespace Ratchet\Mock;
+use Ratchet\MessageComponentInterface;
+use Ratchet\WebSocket\WsServerInterface;
+use Ratchet\ConnectionInterface;
+
+class Component implements MessageComponentInterface, WsServerInterface {
+ public $last = array();
+
+ public $protocols = array();
+
+ public function __construct(ComponentInterface $app = null) {
+ $this->last[__FUNCTION__] = func_get_args();
+ }
+
+ public function onOpen(ConnectionInterface $conn) {
+ $this->last[__FUNCTION__] = func_get_args();
+ }
+
+ public function onMessage(ConnectionInterface $from, $msg) {
+ $this->last[__FUNCTION__] = func_get_args();
+ }
+
+ public function onClose(ConnectionInterface $conn) {
+ $this->last[__FUNCTION__] = func_get_args();
+ }
+
+ public function onError(ConnectionInterface $conn, \Exception $e) {
+ $this->last[__FUNCTION__] = func_get_args();
+ }
+
+ public function getSubProtocols() {
+ return $this->protocols;
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/Connection.php b/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/Connection.php
new file mode 100644
index 0000000..5918296
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/Connection.php
@@ -0,0 +1,20 @@
+<?php
+namespace Ratchet\Mock;
+use Ratchet\ConnectionInterface;
+
+class Connection implements ConnectionInterface {
+ public $last = array(
+ 'send' => ''
+ , 'close' => false
+ );
+
+ public $remoteAddress = '127.0.0.1';
+
+ public function send($data) {
+ $this->last[__FUNCTION__] = $data;
+ }
+
+ public function close() {
+ $this->last[__FUNCTION__] = true;
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/ConnectionDecorator.php b/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/ConnectionDecorator.php
new file mode 100644
index 0000000..5570c07
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/ConnectionDecorator.php
@@ -0,0 +1,22 @@
+<?php
+namespace Ratchet\Mock;
+use Ratchet\AbstractConnectionDecorator;
+
+class ConnectionDecorator extends AbstractConnectionDecorator {
+ public $last = array(
+ 'write' => ''
+ , 'end' => false
+ );
+
+ public function send($data) {
+ $this->last[__FUNCTION__] = $data;
+
+ $this->getConnection()->send($data);
+ }
+
+ public function close() {
+ $this->last[__FUNCTION__] = true;
+
+ $this->getConnection()->close();
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/WampComponent.php b/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/WampComponent.php
new file mode 100644
index 0000000..cd526cb
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Mock/WampComponent.php
@@ -0,0 +1,43 @@
+<?php
+namespace Ratchet\Mock;
+use Ratchet\Wamp\WampServerInterface;
+use Ratchet\WebSocket\WsServerInterface;
+use Ratchet\ConnectionInterface;
+
+class WampComponent implements WampServerInterface, WsServerInterface {
+ public $last = array();
+
+ public $protocols = array();
+
+ public function getSubProtocols() {
+ return $this->protocols;
+ }
+
+ public function onCall(ConnectionInterface $conn, $id, $procURI, array $params) {
+ $this->last[__FUNCTION__] = func_get_args();
+ }
+
+ public function onSubscribe(ConnectionInterface $conn, $topic) {
+ $this->last[__FUNCTION__] = func_get_args();
+ }
+
+ public function onUnSubscribe(ConnectionInterface $conn, $topic) {
+ $this->last[__FUNCTION__] = func_get_args();
+ }
+
+ public function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible) {
+ $this->last[__FUNCTION__] = func_get_args();
+ }
+
+ public function onOpen(ConnectionInterface $conn) {
+ $this->last[__FUNCTION__] = func_get_args();
+ }
+
+ public function onClose(ConnectionInterface $conn) {
+ $this->last[__FUNCTION__] = func_get_args();
+ }
+
+ public function onError(ConnectionInterface $conn, \Exception $e) {
+ $this->last[__FUNCTION__] = func_get_args();
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/NullComponent.php b/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/NullComponent.php
new file mode 100644
index 0000000..90def21
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/NullComponent.php
@@ -0,0 +1,28 @@
+<?php
+namespace Ratchet;
+use Ratchet\ConnectionInterface;
+use Ratchet\MessageComponentInterface;
+use Ratchet\WebSocket\WsServerInterface;
+use Ratchet\Wamp\WampServerInterface;
+
+class NullComponent implements MessageComponentInterface, WsServerInterface, WampServerInterface {
+ public function onOpen(ConnectionInterface $conn) {}
+
+ public function onMessage(ConnectionInterface $conn, $msg) {}
+
+ public function onClose(ConnectionInterface $conn) {}
+
+ public function onError(ConnectionInterface $conn, \Exception $e) {}
+
+ public function onCall(ConnectionInterface $conn, $id, $topic, array $params) {}
+
+ public function onSubscribe(ConnectionInterface $conn, $topic) {}
+
+ public function onUnSubscribe(ConnectionInterface $conn, $topic) {}
+
+ public function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude = array(), array $eligible = array()) {}
+
+ public function getSubProtocols() {
+ return array();
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Wamp/Stub/WsWampServerInterface.php b/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Wamp/Stub/WsWampServerInterface.php
new file mode 100644
index 0000000..197bbd3
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/Wamp/Stub/WsWampServerInterface.php
@@ -0,0 +1,7 @@
+<?php
+namespace Ratchet\Wamp\Stub;
+use Ratchet\WebSocket\WsServerInterface;
+use Ratchet\Wamp\WampServerInterface;
+
+interface WsWampServerInterface extends WsServerInterface, WampServerInterface {
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/WebSocket/Stub/WsMessageComponentInterface.php b/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/WebSocket/Stub/WsMessageComponentInterface.php
new file mode 100644
index 0000000..ef88325
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/helpers/Ratchet/WebSocket/Stub/WsMessageComponentInterface.php
@@ -0,0 +1,7 @@
+<?php
+namespace Ratchet\WebSocket\Stub;
+use Ratchet\MessageComponentInterface;
+use Ratchet\WebSocket\WsServerInterface;
+
+interface WsMessageComponentInterface extends MessageComponentInterface, WsServerInterface {
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/unit/AbstractConnectionDecoratorTest.php b/assets/php/vendor/cboden/ratchet/tests/unit/AbstractConnectionDecoratorTest.php
new file mode 100644
index 0000000..0887d3e
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/unit/AbstractConnectionDecoratorTest.php
@@ -0,0 +1,147 @@
+<?php
+namespace Ratchet;
+use Ratchet\Mock\ConnectionDecorator;
+
+/**
+ * @covers Ratchet\AbstractConnectionDecorator
+ * @covers Ratchet\ConnectionInterface
+ */
+class AbstractConnectionDecoratorTest extends \PHPUnit_Framework_TestCase {
+ protected $mock;
+ protected $l1;
+ protected $l2;
+
+ public function setUp() {
+ $this->mock = $this->getMock('\Ratchet\ConnectionInterface');
+ $this->l1 = new ConnectionDecorator($this->mock);
+ $this->l2 = new ConnectionDecorator($this->l1);
+ }
+
+ public function testGet() {
+ $var = 'hello';
+ $val = 'world';
+
+ $this->mock->$var = $val;
+
+ $this->assertEquals($val, $this->l1->$var);
+ $this->assertEquals($val, $this->l2->$var);
+ }
+
+ public function testSet() {
+ $var = 'Chris';
+ $val = 'Boden';
+
+ $this->l1->$var = $val;
+
+ $this->assertEquals($val, $this->mock->$var);
+ }
+
+ public function testSetLevel2() {
+ $var = 'Try';
+ $val = 'Again';
+
+ $this->l2->$var = $val;
+
+ $this->assertEquals($val, $this->mock->$var);
+ }
+
+ public function testIsSetTrue() {
+ $var = 'PHP';
+ $val = 'Ratchet';
+
+ $this->mock->$var = $val;
+
+ $this->assertTrue(isset($this->l1->$var));
+ $this->assertTrue(isset($this->l2->$var));
+ }
+
+ public function testIsSetFalse() {
+ $var = 'herp';
+ $val = 'derp';
+
+ $this->assertFalse(isset($this->l1->$var));
+ $this->assertFalse(isset($this->l2->$var));
+ }
+
+ public function testUnset() {
+ $var = 'Flying';
+ $val = 'Monkey';
+
+ $this->mock->$var = $val;
+ unset($this->l1->$var);
+
+ $this->assertFalse(isset($this->mock->$var));
+ }
+
+ public function testUnsetLevel2() {
+ $var = 'Flying';
+ $val = 'Monkey';
+
+ $this->mock->$var = $val;
+ unset($this->l2->$var);
+
+ $this->assertFalse(isset($this->mock->$var));
+ }
+
+ public function testGetConnection() {
+ $class = new \ReflectionClass('\\Ratchet\\AbstractConnectionDecorator');
+ $method = $class->getMethod('getConnection');
+ $method->setAccessible(true);
+
+ $conn = $method->invokeArgs($this->l1, array());
+
+ $this->assertSame($this->mock, $conn);
+ }
+
+ public function testGetConnectionLevel2() {
+ $class = new \ReflectionClass('\\Ratchet\\AbstractConnectionDecorator');
+ $method = $class->getMethod('getConnection');
+ $method->setAccessible(true);
+
+ $conn = $method->invokeArgs($this->l2, array());
+
+ $this->assertSame($this->l1, $conn);
+ }
+
+ public function testWrapperCanStoreSelfInDecorator() {
+ $this->mock->decorator = $this->l1;
+
+ $this->assertSame($this->l1, $this->l2->decorator);
+ }
+
+ public function testDecoratorRecursion() {
+ $this->mock->decorator = new \stdClass;
+ $this->mock->decorator->conn = $this->l1;
+
+ $this->assertSame($this->l1, $this->mock->decorator->conn);
+ $this->assertSame($this->l1, $this->l1->decorator->conn);
+ $this->assertSame($this->l1, $this->l2->decorator->conn);
+ }
+
+ public function testDecoratorRecursionLevel2() {
+ $this->mock->decorator = new \stdClass;
+ $this->mock->decorator->conn = $this->l2;
+
+ $this->assertSame($this->l2, $this->mock->decorator->conn);
+ $this->assertSame($this->l2, $this->l1->decorator->conn);
+ $this->assertSame($this->l2, $this->l2->decorator->conn);
+
+ // just for fun
+ $this->assertSame($this->l2, $this->l2->decorator->conn->decorator->conn->decorator->conn);
+ }
+
+ public function testWarningGettingNothing() {
+ $this->setExpectedException('PHPUnit_Framework_Error');
+ $var = $this->mock->nonExistant;
+ }
+
+ public function testWarningGettingNothingLevel1() {
+ $this->setExpectedException('PHPUnit_Framework_Error');
+ $var = $this->l1->nonExistant;
+ }
+
+ public function testWarningGettingNothingLevel2() {
+ $this->setExpectedException('PHPUnit_Framework_Error');
+ $var = $this->l2->nonExistant;
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/unit/Http/HttpRequestParserTest.php b/assets/php/vendor/cboden/ratchet/tests/unit/Http/HttpRequestParserTest.php
new file mode 100644
index 0000000..6af8402
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/unit/Http/HttpRequestParserTest.php
@@ -0,0 +1,50 @@
+<?php
+namespace Ratchet\Http;
+
+/**
+ * @covers Ratchet\Http\HttpRequestParser
+ */
+class HttpRequestParserTest extends \PHPUnit_Framework_TestCase {
+ protected $parser;
+
+ public function setUp() {
+ $this->parser = new HttpRequestParser;
+ }
+
+ public function headersProvider() {
+ return array(
+ array(false, "GET / HTTP/1.1\r\nHost: socketo.me\r\n")
+ , array(true, "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\n")
+ , array(true, "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\n1")
+ , array(true, "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\nHixie✖")
+ , array(true, "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\nHixie✖\r\n\r\n")
+ , array(true, "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\nHixie\r\n")
+ );
+ }
+
+ /**
+ * @dataProvider headersProvider
+ */
+ public function testIsEom($expected, $message) {
+ $this->assertEquals($expected, $this->parser->isEom($message));
+ }
+
+ public function testBufferOverflowResponse() {
+ $conn = $this->getMock('\Ratchet\ConnectionInterface');
+
+ $this->parser->maxSize = 20;
+
+ $this->assertNull($this->parser->onMessage($conn, "GET / HTTP/1.1\r\n"));
+
+ $this->setExpectedException('OverflowException');
+
+ $this->parser->onMessage($conn, "Header-Is: Too Big");
+ }
+
+ public function testReturnTypeIsRequest() {
+ $conn = $this->getMock('\Ratchet\ConnectionInterface');
+ $return = $this->parser->onMessage($conn, "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\n");
+
+ $this->assertInstanceOf('\Psr\Http\Message\RequestInterface', $return);
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/unit/Http/HttpServerTest.php b/assets/php/vendor/cboden/ratchet/tests/unit/Http/HttpServerTest.php
new file mode 100644
index 0000000..7041d66
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/unit/Http/HttpServerTest.php
@@ -0,0 +1,64 @@
+<?php
+namespace Ratchet\Http;
+use Ratchet\AbstractMessageComponentTestCase;
+
+/**
+ * @covers Ratchet\Http\HttpServer
+ */
+class HttpServerTest extends AbstractMessageComponentTestCase {
+ public function setUp() {
+ parent::setUp();
+ $this->_conn->httpHeadersReceived = true;
+ }
+
+ public function getConnectionClassString() {
+ return '\Ratchet\ConnectionInterface';
+ }
+
+ public function getDecoratorClassString() {
+ return '\Ratchet\Http\HttpServer';
+ }
+
+ public function getComponentClassString() {
+ return '\Ratchet\Http\HttpServerInterface';
+ }
+
+ public function testOpen() {
+ $headers = "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\n";
+
+ $this->_conn->httpHeadersReceived = false;
+ $this->_app->expects($this->once())->method('onOpen')->with($this->isExpectedConnection());
+ $this->_serv->onMessage($this->_conn, $headers);
+ }
+
+ public function testOnMessageAfterHeaders() {
+ $headers = "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\n";
+ $this->_conn->httpHeadersReceived = false;
+ $this->_serv->onMessage($this->_conn, $headers);
+
+ $message = "Hello World!";
+ $this->_app->expects($this->once())->method('onMessage')->with($this->isExpectedConnection(), $message);
+ $this->_serv->onMessage($this->_conn, $message);
+ }
+
+ public function testBufferOverflow() {
+ $this->_conn->expects($this->once())->method('close');
+ $this->_conn->httpHeadersReceived = false;
+
+ $this->_serv->onMessage($this->_conn, str_repeat('a', 5000));
+ }
+
+ public function testCloseIfNotEstablished() {
+ $this->_conn->httpHeadersReceived = false;
+ $this->_conn->expects($this->once())->method('close');
+ $this->_serv->onError($this->_conn, new \Exception('Whoops!'));
+ }
+
+ public function testBufferHeaders() {
+ $this->_conn->httpHeadersReceived = false;
+ $this->_app->expects($this->never())->method('onOpen');
+ $this->_app->expects($this->never())->method('onMessage');
+
+ $this->_serv->onMessage($this->_conn, "GET / HTTP/1.1");
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/unit/Http/OriginCheckTest.php b/assets/php/vendor/cboden/ratchet/tests/unit/Http/OriginCheckTest.php
new file mode 100644
index 0000000..c1c4012
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/unit/Http/OriginCheckTest.php
@@ -0,0 +1,46 @@
+<?php
+namespace Ratchet\Http;
+use Ratchet\AbstractMessageComponentTestCase;
+
+/**
+ * @covers Ratchet\Http\OriginCheck
+ */
+class OriginCheckTest extends AbstractMessageComponentTestCase {
+ protected $_reqStub;
+
+ public function setUp() {
+ $this->_reqStub = $this->getMock('Psr\Http\Message\RequestInterface');
+ $this->_reqStub->expects($this->any())->method('getHeader')->will($this->returnValue(['localhost']));
+
+ parent::setUp();
+
+ $this->_serv->allowedOrigins[] = 'localhost';
+ }
+
+ protected function doOpen($conn) {
+ $this->_serv->onOpen($conn, $this->_reqStub);
+ }
+
+ public function getConnectionClassString() {
+ return '\Ratchet\ConnectionInterface';
+ }
+
+ public function getDecoratorClassString() {
+ return '\Ratchet\Http\OriginCheck';
+ }
+
+ public function getComponentClassString() {
+ return '\Ratchet\Http\HttpServerInterface';
+ }
+
+ public function testCloseOnNonMatchingOrigin() {
+ $this->_serv->allowedOrigins = ['socketo.me'];
+ $this->_conn->expects($this->once())->method('close');
+
+ $this->_serv->onOpen($this->_conn, $this->_reqStub);
+ }
+
+ public function testOnMessage() {
+ $this->passthroughMessageTest('Hello World!');
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/unit/Http/RouterTest.php b/assets/php/vendor/cboden/ratchet/tests/unit/Http/RouterTest.php
new file mode 100644
index 0000000..1ca4cbc
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/unit/Http/RouterTest.php
@@ -0,0 +1,165 @@
+<?php
+namespace Ratchet\Http;
+use Ratchet\WebSocket\WsServerInterface;
+use Symfony\Component\Routing\Exception\ResourceNotFoundException;
+use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
+use Symfony\Component\Routing\RequestContext;
+use Symfony\Component\Routing\RouteCollection;
+use Symfony\Component\Routing\Matcher\UrlMatcher;
+
+
+/**
+ * @covers Ratchet\Http\Router
+ */
+class RouterTest extends \PHPUnit_Framework_TestCase {
+ protected $_router;
+ protected $_matcher;
+ protected $_conn;
+ protected $_uri;
+ protected $_req;
+
+ public function setUp() {
+ $this->_conn = $this->getMock('\Ratchet\ConnectionInterface');
+ $this->_uri = $this->getMock('Psr\Http\Message\UriInterface');
+ $this->_req = $this->getMock('\Psr\Http\Message\RequestInterface');
+ $this->_req
+ ->expects($this->any())
+ ->method('getUri')
+ ->will($this->returnValue($this->_uri));
+ $this->_matcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface');
+ $this->_matcher
+ ->expects($this->any())
+ ->method('getContext')
+ ->will($this->returnValue($this->getMock('Symfony\Component\Routing\RequestContext')));
+ $this->_router = new Router($this->_matcher);
+
+ $this->_uri->expects($this->any())->method('getPath')->will($this->returnValue('ws://doesnt.matter/'));
+ $this->_uri->expects($this->any())->method('withQuery')->with($this->callback(function($val) {
+ $this->setResult($val);
+
+ return true;
+ }))->will($this->returnSelf());
+ $this->_uri->expects($this->any())->method('getQuery')->will($this->returnCallback([$this, 'getResult']));
+ $this->_req->expects($this->any())->method('withUri')->will($this->returnSelf());
+ }
+
+ public function testFourOhFour() {
+ $this->_conn->expects($this->once())->method('close');
+
+ $nope = new ResourceNotFoundException;
+ $this->_matcher->expects($this->any())->method('match')->will($this->throwException($nope));
+
+ $this->_router->onOpen($this->_conn, $this->_req);
+ }
+
+ public function testNullRequest() {
+ $this->setExpectedException('\UnexpectedValueException');
+ $this->_router->onOpen($this->_conn);
+ }
+
+ public function testControllerIsMessageComponentInterface() {
+ $this->setExpectedException('\UnexpectedValueException');
+ $this->_matcher->expects($this->any())->method('match')->will($this->returnValue(array('_controller' => new \StdClass)));
+ $this->_router->onOpen($this->_conn, $this->_req);
+ }
+
+ public function testControllerOnOpen() {
+ $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock();
+ $this->_matcher->expects($this->any())->method('match')->will($this->returnValue(array('_controller' => $controller)));
+ $this->_router->onOpen($this->_conn, $this->_req);
+
+ $expectedConn = new \PHPUnit_Framework_Constraint_IsInstanceOf('\Ratchet\ConnectionInterface');
+ $controller->expects($this->once())->method('onOpen')->with($expectedConn, $this->_req);
+
+ $this->_matcher->expects($this->any())->method('match')->will($this->returnValue(array('_controller' => $controller)));
+ $this->_router->onOpen($this->_conn, $this->_req);
+ }
+
+ public function testControllerOnMessageBubbles() {
+ $message = "The greatest trick the Devil ever pulled was convincing the world he didn't exist";
+ $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock();
+ $controller->expects($this->once())->method('onMessage')->with($this->_conn, $message);
+
+ $this->_conn->controller = $controller;
+
+ $this->_router->onMessage($this->_conn, $message);
+ }
+
+ public function testControllerOnCloseBubbles() {
+ $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock();
+ $controller->expects($this->once())->method('onClose')->with($this->_conn);
+
+ $this->_conn->controller = $controller;
+
+ $this->_router->onClose($this->_conn);
+ }
+
+ public function testControllerOnErrorBubbles() {
+ $e= new \Exception('One cannot be betrayed if one has no exceptions');
+ $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock();
+ $controller->expects($this->once())->method('onError')->with($this->_conn, $e);
+
+ $this->_conn->controller = $controller;
+
+ $this->_router->onError($this->_conn, $e);
+ }
+
+ public function testRouterGeneratesRouteParameters() {
+ /** @var $controller WsServerInterface */
+ $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock();
+ /** @var $matcher UrlMatcherInterface */
+ $this->_matcher->expects($this->any())->method('match')->will(
+ $this->returnValue(['_controller' => $controller, 'foo' => 'bar', 'baz' => 'qux'])
+ );
+ $conn = $this->getMock('Ratchet\Mock\Connection');
+
+ $router = new Router($this->_matcher);
+
+ $router->onOpen($conn, $this->_req);
+
+ $this->assertEquals('foo=bar&baz=qux', $this->_req->getUri()->getQuery());
+ }
+
+ public function testQueryParams() {
+ $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock();
+ $this->_matcher->expects($this->any())->method('match')->will(
+ $this->returnValue(['_controller' => $controller, 'foo' => 'bar', 'baz' => 'qux'])
+ );
+
+ $conn = $this->getMock('Ratchet\Mock\Connection');
+ $request = $this->getMock('Psr\Http\Message\RequestInterface');
+ $uri = new \GuzzleHttp\Psr7\Uri('ws://doesnt.matter/endpoint?hello=world&foo=nope');
+
+ $request->expects($this->any())->method('getUri')->will($this->returnCallback(function() use (&$uri) {
+ return $uri;
+ }));
+ $request->expects($this->any())->method('withUri')->with($this->callback(function($url) use (&$uri) {
+ $uri = $url;
+
+ return true;
+ }))->will($this->returnSelf());
+
+ $router = new Router($this->_matcher);
+ $router->onOpen($conn, $request);
+
+ $this->assertEquals('foo=nope&baz=qux&hello=world', $request->getUri()->getQuery());
+ $this->assertEquals('ws', $request->getUri()->getScheme());
+ $this->assertEquals('doesnt.matter', $request->getUri()->getHost());
+ }
+
+ public function testImpatientClientOverflow() {
+ $this->_conn->expects($this->once())->method('close');
+
+ $header = "GET /nope HTTP/1.1
+Upgrade: websocket
+Connection: upgrade
+Host: localhost
+Origin: http://localhost
+Sec-WebSocket-Version: 13\r\n\r\n";
+
+ $app = new HttpServer(new Router(new UrlMatcher(new RouteCollection, new RequestContext)));
+ $app->onOpen($this->_conn);
+ $app->onMessage($this->_conn, $header);
+ $app->onMessage($this->_conn, 'Silly body');
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/unit/Server/EchoServerTest.php b/assets/php/vendor/cboden/ratchet/tests/unit/Server/EchoServerTest.php
new file mode 100644
index 0000000..47fb0e2
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/unit/Server/EchoServerTest.php
@@ -0,0 +1,26 @@
+<?php
+namespace Ratchet\Server;
+use Ratchet\Server\EchoServer;
+
+class EchoServerTest extends \PHPUnit_Framework_TestCase {
+ protected $_conn;
+ protected $_comp;
+
+ public function setUp() {
+ $this->_conn = $this->getMock('\Ratchet\ConnectionInterface');
+ $this->_comp = new EchoServer;
+ }
+
+ public function testMessageEchod() {
+ $message = 'Tillsonburg, my back still aches when I hear that word.';
+ $this->_conn->expects($this->once())->method('send')->with($message);
+ $this->_comp->onMessage($this->_conn, $message);
+ }
+
+ public function testErrorClosesConnection() {
+ ob_start();
+ $this->_conn->expects($this->once())->method('close');
+ $this->_comp->onError($this->_conn, new \Exception);
+ ob_end_clean();
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/unit/Server/FlashPolicyComponentTest.php b/assets/php/vendor/cboden/ratchet/tests/unit/Server/FlashPolicyComponentTest.php
new file mode 100644
index 0000000..38fc96a
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/unit/Server/FlashPolicyComponentTest.php
@@ -0,0 +1,152 @@
+<?php
+namespace Ratchet\Application\Server;
+use Ratchet\Server\FlashPolicy;
+
+/**
+ * @covers Ratchet\Server\FlashPolicy
+ */
+class FlashPolicyTest extends \PHPUnit_Framework_TestCase {
+
+ protected $_policy;
+
+ public function setUp() {
+ $this->_policy = new FlashPolicy();
+ }
+
+ public function testPolicyRender() {
+ $this->_policy->setSiteControl('all');
+ $this->_policy->addAllowedAccess('example.com', '*');
+ $this->_policy->addAllowedAccess('dev.example.com', '*');
+
+ $this->assertInstanceOf('SimpleXMLElement', $this->_policy->renderPolicy());
+ }
+
+ public function testInvalidPolicyReader() {
+ $this->setExpectedException('UnexpectedValueException');
+ $this->_policy->renderPolicy();
+ }
+
+ public function testInvalidDomainPolicyReader() {
+ $this->setExpectedException('UnexpectedValueException');
+ $this->_policy->setSiteControl('all');
+ $this->_policy->addAllowedAccess('dev.example.*', '*');
+ $this->_policy->renderPolicy();
+ }
+
+ /**
+ * @dataProvider siteControl
+ */
+ public function testSiteControlValidation($accept, $permittedCrossDomainPolicies) {
+ $this->assertEquals($accept, $this->_policy->validateSiteControl($permittedCrossDomainPolicies));
+ }
+
+ public static function siteControl() {
+ return array(
+ array(true, 'all')
+ , array(true, 'none')
+ , array(true, 'master-only')
+ , array(false, 'by-content-type')
+ , array(false, 'by-ftp-filename')
+ , array(false, '')
+ , array(false, 'all ')
+ , array(false, 'asdf')
+ , array(false, '@893830')
+ , array(false, '*')
+ );
+ }
+
+ /**
+ * @dataProvider URI
+ */
+ public function testDomainValidation($accept, $domain) {
+ $this->assertEquals($accept, $this->_policy->validateDomain($domain));
+ }
+
+ public static function URI() {
+ return array(
+ array(true, '*')
+ , array(true, 'example.com')
+ , array(true, 'exam-ple.com')
+ , array(true, '*.example.com')
+ , array(true, 'www.example.com')
+ , array(true, 'dev.dev.example.com')
+ , array(true, 'http://example.com')
+ , array(true, 'https://example.com')
+ , array(true, 'http://*.example.com')
+ , array(false, 'exam*ple.com')
+ , array(true, '127.0.255.1')
+ , array(true, 'localhost')
+ , array(false, 'www.example.*')
+ , array(false, 'www.exa*le.com')
+ , array(false, 'www.example.*com')
+ , array(false, '*.example.*')
+ , array(false, 'gasldf*$#a0sdf0a8sdf')
+ );
+ }
+
+ /**
+ * @dataProvider ports
+ */
+ public function testPortValidation($accept, $ports) {
+ $this->assertEquals($accept, $this->_policy->validatePorts($ports));
+ }
+
+ public static function ports() {
+ return array(
+ array(true, '*')
+ , array(true, '80')
+ , array(true, '80,443')
+ , array(true, '507,516-523')
+ , array(true, '507,516-523,333')
+ , array(true, '507,516-523,507,516-523')
+ , array(false, '516-')
+ , array(true, '516-523,11')
+ , array(false, '516,-523,11')
+ , array(false, 'example')
+ , array(false, 'asdf,123')
+ , array(false, '--')
+ , array(false, ',,,')
+ , array(false, '838*')
+ );
+ }
+
+ public function testAddAllowedAccessOnlyAcceptsValidPorts() {
+ $this->setExpectedException('UnexpectedValueException');
+
+ $this->_policy->addAllowedAccess('*', 'nope');
+ }
+
+ public function testSetSiteControlThrowsException() {
+ $this->setExpectedException('UnexpectedValueException');
+
+ $this->_policy->setSiteControl('nope');
+ }
+
+ public function testErrorClosesConnection() {
+ $conn = $this->getMock('\\Ratchet\\ConnectionInterface');
+ $conn->expects($this->once())->method('close');
+
+ $this->_policy->onError($conn, new \Exception);
+ }
+
+ public function testOnMessageSendsString() {
+ $this->_policy->addAllowedAccess('*', '*');
+
+ $conn = $this->getMock('\\Ratchet\\ConnectionInterface');
+ $conn->expects($this->once())->method('send')->with($this->isType('string'));
+
+ $this->_policy->onMessage($conn, ' ');
+ }
+
+ public function testOnOpenExists() {
+ $this->assertTrue(method_exists($this->_policy, 'onOpen'));
+ $conn = $this->getMock('\Ratchet\ConnectionInterface');
+ $this->_policy->onOpen($conn);
+ }
+
+ public function testOnCloseExists() {
+ $this->assertTrue(method_exists($this->_policy, 'onClose'));
+ $conn = $this->getMock('\Ratchet\ConnectionInterface');
+ $this->_policy->onClose($conn);
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/unit/Server/IoConnectionTest.php b/assets/php/vendor/cboden/ratchet/tests/unit/Server/IoConnectionTest.php
new file mode 100644
index 0000000..07130f6
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/unit/Server/IoConnectionTest.php
@@ -0,0 +1,32 @@
+<?php
+namespace Ratchet\Application\Server;
+use Ratchet\Server\IoConnection;
+
+/**
+ * @covers Ratchet\Server\IoConnection
+ */
+class IoConnectionTest extends \PHPUnit_Framework_TestCase {
+ protected $sock;
+ protected $conn;
+
+ public function setUp() {
+ $this->sock = $this->getMock('\\React\\Socket\\ConnectionInterface');
+ $this->conn = new IoConnection($this->sock);
+ }
+
+ public function testCloseBubbles() {
+ $this->sock->expects($this->once())->method('end');
+ $this->conn->close();
+ }
+
+ public function testSendBubbles() {
+ $msg = '6 hour rides are productive';
+
+ $this->sock->expects($this->once())->method('write')->with($msg);
+ $this->conn->send($msg);
+ }
+
+ public function testSendReturnsSelf() {
+ $this->assertSame($this->conn, $this->conn->send('fluent interface'));
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/unit/Server/IoServerTest.php b/assets/php/vendor/cboden/ratchet/tests/unit/Server/IoServerTest.php
new file mode 100644
index 0000000..284fbde
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/unit/Server/IoServerTest.php
@@ -0,0 +1,118 @@
+<?php
+namespace Ratchet\Server;
+use Ratchet\Server\IoServer;
+use React\EventLoop\StreamSelectLoop;
+use React\Socket\Server;
+
+/**
+ * @covers Ratchet\Server\IoServer
+ */
+class IoServerTest extends \PHPUnit_Framework_TestCase {
+ protected $server;
+
+ protected $app;
+
+ protected $port;
+
+ protected $reactor;
+
+ public function setUp() {
+ $this->app = $this->getMock('\\Ratchet\\MessageComponentInterface');
+
+ $loop = new StreamSelectLoop;
+ $this->reactor = new Server(0, $loop);
+
+ $uri = $this->reactor->getAddress();
+ $this->port = parse_url((strpos($uri, '://') === false ? 'tcp://' : '') . $uri, PHP_URL_PORT);
+ $this->server = new IoServer($this->app, $this->reactor, $loop);
+ }
+
+ public function testOnOpen() {
+ $this->app->expects($this->once())->method('onOpen')->with($this->isInstanceOf('\\Ratchet\\ConnectionInterface'));
+
+ $client = stream_socket_client("tcp://localhost:{$this->port}");
+
+ $this->server->loop->tick();
+
+ //$this->assertTrue(is_string($this->app->last['onOpen'][0]->remoteAddress));
+ //$this->assertTrue(is_int($this->app->last['onOpen'][0]->resourceId));
+ }
+
+ public function testOnData() {
+ $msg = 'Hello World!';
+
+ $this->app->expects($this->once())->method('onMessage')->with(
+ $this->isInstanceOf('\\Ratchet\\ConnectionInterface')
+ , $msg
+ );
+
+ $client = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
+ socket_set_option($client, SOL_SOCKET, SO_REUSEADDR, 1);
+ socket_set_option($client, SOL_SOCKET, SO_SNDBUF, 4096);
+ socket_set_block($client);
+ socket_connect($client, 'localhost', $this->port);
+
+ $this->server->loop->tick();
+
+ socket_write($client, $msg);
+ $this->server->loop->tick();
+
+ socket_shutdown($client, 1);
+ socket_shutdown($client, 0);
+ socket_close($client);
+
+ $this->server->loop->tick();
+ }
+
+ public function testOnClose() {
+ $this->app->expects($this->once())->method('onClose')->with($this->isInstanceOf('\\Ratchet\\ConnectionInterface'));
+
+ $client = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
+ socket_set_option($client, SOL_SOCKET, SO_REUSEADDR, 1);
+ socket_set_option($client, SOL_SOCKET, SO_SNDBUF, 4096);
+ socket_set_block($client);
+ socket_connect($client, 'localhost', $this->port);
+
+ $this->server->loop->tick();
+
+ socket_shutdown($client, 1);
+ socket_shutdown($client, 0);
+ socket_close($client);
+
+ $this->server->loop->tick();
+ }
+
+ public function testFactory() {
+ $this->assertInstanceOf('\\Ratchet\\Server\\IoServer', IoServer::factory($this->app, 0));
+ }
+
+ public function testNoLoopProvidedError() {
+ $this->setExpectedException('RuntimeException');
+
+ $io = new IoServer($this->app, $this->reactor);
+ $io->run();
+ }
+
+ public function testOnErrorPassesException() {
+ $conn = $this->getMock('\\React\\Socket\\ConnectionInterface');
+ $conn->decor = $this->getMock('\\Ratchet\\ConnectionInterface');
+ $err = new \Exception("Nope");
+
+ $this->app->expects($this->once())->method('onError')->with($conn->decor, $err);
+
+ $this->server->handleError($err, $conn);
+ }
+
+ public function onErrorCalledWhenExceptionThrown() {
+ $this->markTestIncomplete("Need to learn how to throw an exception from a mock");
+
+ $conn = $this->getMock('\\React\\Socket\\ConnectionInterface');
+ $this->server->handleConnect($conn);
+
+ $e = new \Exception;
+ $this->app->expects($this->once())->method('onMessage')->with($this->isInstanceOf('\\Ratchet\\ConnectionInterface'), 'f')->will($e);
+ $this->app->expects($this->once())->method('onError')->with($this->instanceOf('\\Ratchet\\ConnectionInterface', $e));
+
+ $this->server->handleData('f', $conn);
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/unit/Server/IpBlackListComponentTest.php b/assets/php/vendor/cboden/ratchet/tests/unit/Server/IpBlackListComponentTest.php
new file mode 100644
index 0000000..90f4185
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/unit/Server/IpBlackListComponentTest.php
@@ -0,0 +1,125 @@
+<?php
+namespace Ratchet\Server;
+use Ratchet\Server\IpBlackList;
+
+/**
+ * @covers Ratchet\Server\IpBlackList
+ */
+class IpBlackListTest extends \PHPUnit_Framework_TestCase {
+ protected $blocker;
+ protected $mock;
+
+ public function setUp() {
+ $this->mock = $this->getMock('\\Ratchet\\MessageComponentInterface');
+ $this->blocker = new IpBlackList($this->mock);
+ }
+
+ public function testOnOpen() {
+ $this->mock->expects($this->exactly(3))->method('onOpen');
+
+ $conn1 = $this->newConn();
+ $conn2 = $this->newConn();
+ $conn3 = $this->newConn();
+
+ $this->blocker->onOpen($conn1);
+ $this->blocker->onOpen($conn3);
+ $this->blocker->onOpen($conn2);
+ }
+
+ public function testBlockDoesNotTriggerOnOpen() {
+ $conn = $this->newConn();
+
+ $this->blocker->blockAddress($conn->remoteAddress);
+
+ $this->mock->expects($this->never())->method('onOpen');
+
+ $ret = $this->blocker->onOpen($conn);
+ }
+
+ public function testBlockDoesNotTriggerOnClose() {
+ $conn = $this->newConn();
+
+ $this->blocker->blockAddress($conn->remoteAddress);
+
+ $this->mock->expects($this->never())->method('onClose');
+
+ $ret = $this->blocker->onOpen($conn);
+ }
+
+ public function testOnMessageDecoration() {
+ $conn = $this->newConn();
+ $msg = 'Hello not being blocked';
+
+ $this->mock->expects($this->once())->method('onMessage')->with($conn, $msg);
+
+ $this->blocker->onMessage($conn, $msg);
+ }
+
+ public function testOnCloseDecoration() {
+ $conn = $this->newConn();
+
+ $this->mock->expects($this->once())->method('onClose')->with($conn);
+
+ $this->blocker->onClose($conn);
+ }
+
+ public function testBlockClosesConnection() {
+ $conn = $this->newConn();
+ $this->blocker->blockAddress($conn->remoteAddress);
+
+ $conn->expects($this->once())->method('close');
+
+ $this->blocker->onOpen($conn);
+ }
+
+ public function testAddAndRemoveWithFluentInterfaces() {
+ $blockOne = '127.0.0.1';
+ $blockTwo = '192.168.1.1';
+ $unblock = '75.119.207.140';
+
+ $this->blocker
+ ->blockAddress($unblock)
+ ->blockAddress($blockOne)
+ ->unblockAddress($unblock)
+ ->blockAddress($blockTwo)
+ ;
+
+ $this->assertEquals(array($blockOne, $blockTwo), $this->blocker->getBlockedAddresses());
+ }
+
+ public function testDecoratorPassesErrors() {
+ $conn = $this->newConn();
+ $e = new \Exception('I threw an error');
+
+ $this->mock->expects($this->once())->method('onError')->with($conn, $e);
+
+ $this->blocker->onError($conn, $e);
+ }
+
+ public function addressProvider() {
+ return array(
+ array('127.0.0.1', '127.0.0.1')
+ , array('localhost', 'localhost')
+ , array('fe80::1%lo0', 'fe80::1%lo0')
+ , array('127.0.0.1', '127.0.0.1:6392')
+ );
+ }
+
+ /**
+ * @dataProvider addressProvider
+ */
+ public function testFilterAddress($expected, $input) {
+ $this->assertEquals($expected, $this->blocker->filterAddress($input));
+ }
+
+ public function testUnblockingSilentlyFails() {
+ $this->assertInstanceOf('\\Ratchet\\Server\\IpBlackList', $this->blocker->unblockAddress('localhost'));
+ }
+
+ protected function newConn() {
+ $conn = $this->getMock('\\Ratchet\\ConnectionInterface');
+ $conn->remoteAddress = '127.0.0.1';
+
+ return $conn;
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/unit/Session/Serialize/PhpHandlerTest.php b/assets/php/vendor/cboden/ratchet/tests/unit/Session/Serialize/PhpHandlerTest.php
new file mode 100644
index 0000000..4acf5bc
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/unit/Session/Serialize/PhpHandlerTest.php
@@ -0,0 +1,43 @@
+<?php
+namespace Ratchet\Session\Serialize;
+use Ratchet\Session\Serialize\PhpHandler;
+
+/**
+ * @covers Ratchet\Session\Serialize\PhpHandler
+ */
+class PhpHandlerTest extends \PHPUnit_Framework_TestCase {
+ protected $_handler;
+
+ public function setUp() {
+ $this->_handler = new PhpHandler;
+ }
+
+ public function serializedProvider() {
+ return array(
+ array(
+ '_sf2_attributes|a:2:{s:5:"hello";s:5:"world";s:4:"last";i:1332872102;}_sf2_flashes|a:0:{}'
+ , array(
+ '_sf2_attributes' => array(
+ 'hello' => 'world'
+ , 'last' => 1332872102
+ )
+ , '_sf2_flashes' => array()
+ )
+ )
+ );
+ }
+
+ /**
+ * @dataProvider serializedProvider
+ */
+ public function testUnserialize($in, $expected) {
+ $this->assertEquals($expected, $this->_handler->unserialize($in));
+ }
+
+ /**
+ * @dataProvider serializedProvider
+ */
+ public function testSerialize($serialized, $original) {
+ $this->assertEquals($serialized, $this->_handler->serialize($original));
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/unit/Session/SessionComponentTest.php b/assets/php/vendor/cboden/ratchet/tests/unit/Session/SessionComponentTest.php
new file mode 100644
index 0000000..ebfdde4
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/unit/Session/SessionComponentTest.php
@@ -0,0 +1,124 @@
+<?php
+namespace Ratchet\Session;
+use Ratchet\AbstractMessageComponentTestCase;
+use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;
+use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler;
+
+/**
+ * @covers Ratchet\Session\SessionProvider
+ * @covers Ratchet\Session\Storage\VirtualSessionStorage
+ * @covers Ratchet\Session\Storage\Proxy\VirtualProxy
+ */
+class SessionProviderTest extends AbstractMessageComponentTestCase {
+ public function setUp() {
+ if (!class_exists('Symfony\Component\HttpFoundation\Session\Session')) {
+ return $this->markTestSkipped('Dependency of Symfony HttpFoundation failed');
+ }
+
+ parent::setUp();
+ $this->_serv = new SessionProvider($this->_app, new NullSessionHandler);
+ }
+
+ public function tearDown() {
+ ini_set('session.serialize_handler', 'php');
+ }
+
+ public function getConnectionClassString() {
+ return '\Ratchet\ConnectionInterface';
+ }
+
+ public function getDecoratorClassString() {
+ return '\Ratchet\NullComponent';
+ }
+
+ public function getComponentClassString() {
+ return '\Ratchet\Http\HttpServerInterface';
+ }
+
+ public function classCaseProvider() {
+ return array(
+ array('php', 'Php')
+ , array('php_binary', 'PhpBinary')
+ );
+ }
+
+ /**
+ * @dataProvider classCaseProvider
+ */
+ public function testToClassCase($in, $out) {
+ $ref = new \ReflectionClass('\\Ratchet\\Session\\SessionProvider');
+ $method = $ref->getMethod('toClassCase');
+ $method->setAccessible(true);
+
+ $component = new SessionProvider($this->getMock($this->getComponentClassString()), $this->getMock('\SessionHandlerInterface'));
+ $this->assertEquals($out, $method->invokeArgs($component, array($in)));
+ }
+
+ /**
+ * I think I have severely butchered this test...it's not so much of a unit test as it is a full-fledged component test
+ */
+ public function testConnectionValueFromPdo() {
+ if (!extension_loaded('PDO') || !extension_loaded('pdo_sqlite')) {
+ return $this->markTestSkipped('Session test requires PDO and pdo_sqlite');
+ }
+
+ $sessionId = md5('testSession');
+
+ $dbOptions = array(
+ 'db_table' => 'sessions'
+ , 'db_id_col' => 'sess_id'
+ , 'db_data_col' => 'sess_data'
+ , 'db_time_col' => 'sess_time'
+ , 'db_lifetime_col' => 'sess_lifetime'
+ );
+
+ $pdo = new \PDO("sqlite::memory:");
+ $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
+ $pdo->exec(vsprintf("CREATE TABLE %s (%s TEXT NOT NULL PRIMARY KEY, %s BLOB NOT NULL, %s INTEGER NOT NULL, %s INTEGER)", $dbOptions));
+
+ $pdoHandler = new PdoSessionHandler($pdo, $dbOptions);
+ $pdoHandler->write($sessionId, '_sf2_attributes|a:2:{s:5:"hello";s:5:"world";s:4:"last";i:1332872102;}_sf2_flashes|a:0:{}');
+
+ $component = new SessionProvider($this->getMock($this->getComponentClassString()), $pdoHandler, array('auto_start' => 1));
+ $connection = $this->getMock('Ratchet\\ConnectionInterface');
+
+ $headers = $this->getMock('Psr\Http\Message\RequestInterface');
+ $headers->expects($this->once())->method('getHeader')->will($this->returnValue([ini_get('session.name') . "={$sessionId};"]));
+
+ $component->onOpen($connection, $headers);
+
+ $this->assertEquals('world', $connection->Session->get('hello'));
+ }
+
+ protected function newConn() {
+ $conn = $this->getMock('Ratchet\ConnectionInterface');
+
+ $headers = $this->getMock('Psr\Http\Message\Request', array('getCookie'), array('POST', '/', array()));
+ $headers->expects($this->once())->method('getCookie', array(ini_get('session.name')))->will($this->returnValue(null));
+
+ return $conn;
+ }
+
+ public function testOnMessageDecorator() {
+ $message = "Database calls are usually blocking :(";
+ $this->_app->expects($this->once())->method('onMessage')->with($this->isExpectedConnection(), $message);
+ $this->_serv->onMessage($this->_conn, $message);
+ }
+
+ public function testRejectInvalidSeralizers() {
+ if (!function_exists('wddx_serialize_value')) {
+ $this->markTestSkipped();
+ }
+
+ ini_set('session.serialize_handler', 'wddx');
+ $this->setExpectedException('\RuntimeException');
+ new SessionProvider($this->getMock($this->getComponentClassString()), $this->getMock('\SessionHandlerInterface'));
+ }
+
+ protected function doOpen($conn) {
+ $request = $this->getMock('Psr\Http\Message\RequestInterface');
+ $request->expects($this->any())->method('getHeader')->will($this->returnValue([]));
+
+ $this->_serv->onOpen($conn, $request);
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/unit/Session/Storage/VirtualSessionStoragePDOTest.php b/assets/php/vendor/cboden/ratchet/tests/unit/Session/Storage/VirtualSessionStoragePDOTest.php
new file mode 100644
index 0000000..2727484
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/unit/Session/Storage/VirtualSessionStoragePDOTest.php
@@ -0,0 +1,53 @@
+<?php
+namespace Ratchet\Session\Storage;
+use Ratchet\Session\Serialize\PhpHandler;
+use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
+use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
+use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;
+
+class VirtualSessionStoragePDOTest extends \PHPUnit_Framework_TestCase {
+ /**
+ * @var VirtualSessionStorage
+ */
+ protected $_virtualSessionStorage;
+
+ protected $_pathToDB;
+
+ public function setUp() {
+ if (!extension_loaded('PDO') || !extension_loaded('pdo_sqlite')) {
+ return $this->markTestSkipped('Session test requires PDO and pdo_sqlite');
+ }
+
+ $schema = <<<SQL
+CREATE TABLE `sessions` (
+ `sess_id` VARBINARY(128) NOT NULL PRIMARY KEY,
+ `sess_data` BLOB NOT NULL,
+ `sess_time` INTEGER UNSIGNED NOT NULL,
+ `sess_lifetime` MEDIUMINT NOT NULL
+);
+SQL;
+ $this->_pathToDB = tempnam(sys_get_temp_dir(), 'SQ3');;
+ $dsn = 'sqlite:' . $this->_pathToDB;
+
+ $pdo = new \PDO($dsn);
+ $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
+ $pdo->exec($schema);
+ $pdo = null;
+
+ $sessionHandler = new PdoSessionHandler($dsn);
+ $serializer = new PhpHandler();
+ $this->_virtualSessionStorage = new VirtualSessionStorage($sessionHandler, 'foobar', $serializer);
+ $this->_virtualSessionStorage->registerBag(new FlashBag());
+ $this->_virtualSessionStorage->registerBag(new AttributeBag());
+ }
+
+ public function tearDown() {
+ unlink($this->_pathToDB);
+ }
+
+ public function testStartWithDSN() {
+ $this->_virtualSessionStorage->start();
+
+ $this->assertTrue($this->_virtualSessionStorage->isStarted());
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/unit/Wamp/ServerProtocolTest.php b/assets/php/vendor/cboden/ratchet/tests/unit/Wamp/ServerProtocolTest.php
new file mode 100644
index 0000000..8ff68c2
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/unit/Wamp/ServerProtocolTest.php
@@ -0,0 +1,295 @@
+<?php
+namespace Ratchet\Wamp;
+use Ratchet\Mock\Connection;
+use Ratchet\Mock\WampComponent as TestComponent;
+
+/**
+ * @covers \Ratchet\Wamp\ServerProtocol
+ * @covers \Ratchet\Wamp\WampServerInterface
+ * @covers \Ratchet\Wamp\WampConnection
+ */
+class ServerProtocolTest extends \PHPUnit_Framework_TestCase {
+ protected $_comp;
+
+ protected $_app;
+
+ public function setUp() {
+ $this->_app = new TestComponent;
+ $this->_comp = new ServerProtocol($this->_app);
+ }
+
+ protected function newConn() {
+ return new Connection;
+ }
+
+ public function invalidMessageProvider() {
+ return [
+ [0]
+ , [3]
+ , [4]
+ , [8]
+ , [9]
+ ];
+ }
+
+ /**
+ * @dataProvider invalidMessageProvider
+ */
+ public function testInvalidMessages($type) {
+ $this->setExpectedException('\Ratchet\Wamp\Exception');
+
+ $conn = $this->newConn();
+ $this->_comp->onOpen($conn);
+ $this->_comp->onMessage($conn, json_encode([$type]));
+ }
+
+ public function testWelcomeMessage() {
+ $conn = $this->newConn();
+
+ $this->_comp->onOpen($conn);
+
+ $message = $conn->last['send'];
+ $json = json_decode($message);
+
+ $this->assertEquals(4, count($json));
+ $this->assertEquals(0, $json[0]);
+ $this->assertTrue(is_string($json[1]));
+ $this->assertEquals(1, $json[2]);
+ }
+
+ public function testSubscribe() {
+ $uri = 'http://example.com';
+ $clientMessage = array(5, $uri);
+
+ $conn = $this->newConn();
+
+ $this->_comp->onOpen($conn);
+ $this->_comp->onMessage($conn, json_encode($clientMessage));
+
+ $this->assertEquals($uri, $this->_app->last['onSubscribe'][1]);
+ }
+
+ public function testUnSubscribe() {
+ $uri = 'http://example.com/endpoint';
+ $clientMessage = array(6, $uri);
+
+ $conn = $this->newConn();
+
+ $this->_comp->onOpen($conn);
+ $this->_comp->onMessage($conn, json_encode($clientMessage));
+
+ $this->assertEquals($uri, $this->_app->last['onUnSubscribe'][1]);
+ }
+
+ public function callProvider() {
+ return [
+ [2, 'a', 'b']
+ , [2, ['a', 'b']]
+ , [1, 'one']
+ , [3, 'one', 'two', 'three']
+ , [3, ['un', 'deux', 'trois']]
+ , [2, 'hi', ['hello', 'world']]
+ , [2, ['hello', 'world'], 'hi']
+ , [2, ['hello' => 'world', 'herp' => 'derp']]
+ ];
+ }
+
+ /**
+ * @dataProvider callProvider
+ */
+ public function testCall() {
+ $args = func_get_args();
+ $paramNum = array_shift($args);
+
+ $uri = 'http://example.com/endpoint/' . rand(1, 100);
+ $id = uniqid('', false);
+ $clientMessage = array_merge(array(2, $id, $uri), $args);
+
+ $conn = $this->newConn();
+
+ $this->_comp->onOpen($conn);
+ $this->_comp->onMessage($conn, json_encode($clientMessage));
+
+ $this->assertEquals($id, $this->_app->last['onCall'][1]);
+ $this->assertEquals($uri, $this->_app->last['onCall'][2]);
+
+ $this->assertEquals($paramNum, count($this->_app->last['onCall'][3]));
+ }
+
+ public function testPublish() {
+ $conn = $this->newConn();
+
+ $topic = 'pubsubhubbub';
+ $event = 'Here I am, publishing data';
+
+ $clientMessage = array(7, $topic, $event);
+
+ $this->_comp->onOpen($conn);
+ $this->_comp->onMessage($conn, json_encode($clientMessage));
+
+ $this->assertEquals($topic, $this->_app->last['onPublish'][1]);
+ $this->assertEquals($event, $this->_app->last['onPublish'][2]);
+ $this->assertEquals(array(), $this->_app->last['onPublish'][3]);
+ $this->assertEquals(array(), $this->_app->last['onPublish'][4]);
+ }
+
+ public function testPublishAndExcludeMe() {
+ $conn = $this->newConn();
+
+ $this->_comp->onOpen($conn);
+ $this->_comp->onMessage($conn, json_encode(array(7, 'topic', 'event', true)));
+
+ $this->assertEquals($conn->WAMP->sessionId, $this->_app->last['onPublish'][3][0]);
+ }
+
+ public function testPublishAndEligible() {
+ $conn = $this->newConn();
+
+ $buddy = uniqid('', false);
+ $friend = uniqid('', false);
+
+ $this->_comp->onOpen($conn);
+ $this->_comp->onMessage($conn, json_encode(array(7, 'topic', 'event', false, array($buddy, $friend))));
+
+ $this->assertEquals(array(), $this->_app->last['onPublish'][3]);
+ $this->assertEquals(2, count($this->_app->last['onPublish'][4]));
+ }
+
+ public function eventProvider() {
+ return array(
+ array('http://example.com', array('one', 'two'))
+ , array('curie', array(array('hello' => 'world', 'herp' => 'derp')))
+ );
+ }
+
+ /**
+ * @dataProvider eventProvider
+ */
+ public function testEvent($topic, $payload) {
+ $conn = new WampConnection($this->newConn());
+ $conn->event($topic, $payload);
+
+ $eventString = $conn->last['send'];
+
+ $this->assertSame(array(8, $topic, $payload), json_decode($eventString, true));
+ }
+
+ public function testOnClosePropagation() {
+ $conn = new Connection;
+
+ $this->_comp->onOpen($conn);
+ $this->_comp->onClose($conn);
+
+ $class = new \ReflectionClass('\\Ratchet\\Wamp\\WampConnection');
+ $method = $class->getMethod('getConnection');
+ $method->setAccessible(true);
+
+ $check = $method->invokeArgs($this->_app->last['onClose'][0], array());
+
+ $this->assertSame($conn, $check);
+ }
+
+ public function testOnErrorPropagation() {
+ $conn = new Connection;
+
+ $e = new \Exception('Nope');
+
+ $this->_comp->onOpen($conn);
+ $this->_comp->onError($conn, $e);
+
+ $class = new \ReflectionClass('\\Ratchet\\Wamp\\WampConnection');
+ $method = $class->getMethod('getConnection');
+ $method->setAccessible(true);
+
+ $check = $method->invokeArgs($this->_app->last['onError'][0], array());
+
+ $this->assertSame($conn, $check);
+ $this->assertSame($e, $this->_app->last['onError'][1]);
+ }
+
+ public function testPrefix() {
+ $conn = new WampConnection($this->newConn());
+ $this->_comp->onOpen($conn);
+
+ $prefix = 'incoming';
+ $fullURI = "http://example.com/$prefix";
+ $method = 'call';
+
+ $this->_comp->onMessage($conn, json_encode(array(1, $prefix, $fullURI)));
+
+ $this->assertEquals($fullURI, $conn->WAMP->prefixes[$prefix]);
+ $this->assertEquals("$fullURI#$method", $conn->getUri("$prefix:$method"));
+ }
+
+ public function testMessageMustBeJson() {
+ $this->setExpectedException('\\Ratchet\\Wamp\\JsonException');
+
+ $conn = new Connection;
+
+ $this->_comp->onOpen($conn);
+ $this->_comp->onMessage($conn, 'Hello World!');
+ }
+
+ public function testGetSubProtocolsReturnsArray() {
+ $this->assertTrue(is_array($this->_comp->getSubProtocols()));
+ }
+
+ public function testGetSubProtocolsGetFromApp() {
+ $this->_app->protocols = array('hello', 'world');
+
+ $this->assertGreaterThanOrEqual(3, count($this->_comp->getSubProtocols()));
+ }
+
+ public function testWampOnMessageApp() {
+ $app = $this->getMock('\\Ratchet\\Wamp\\WampServerInterface');
+ $wamp = new ServerProtocol($app);
+
+ $this->assertContains('wamp', $wamp->getSubProtocols());
+ }
+
+ public function badFormatProvider() {
+ return array(
+ array(json_encode(true))
+ , array('{"valid":"json", "invalid": "message"}')
+ , array('{"0": "fail", "hello": "world"}')
+ );
+ }
+
+ /**
+ * @dataProvider badFormatProvider
+ */
+ public function testValidJsonButInvalidProtocol($message) {
+ $this->setExpectedException('\Ratchet\Wamp\Exception');
+
+ $conn = $this->newConn();
+ $this->_comp->onOpen($conn);
+ $this->_comp->onMessage($conn, $message);
+ }
+
+ public function testBadClientInputFromNonStringTopic() {
+ $this->setExpectedException('\Ratchet\Wamp\Exception');
+
+ $conn = new WampConnection($this->newConn());
+ $this->_comp->onOpen($conn);
+
+ $this->_comp->onMessage($conn, json_encode([5, ['hells', 'nope']]));
+ }
+
+ public function testBadPrefixWithNonStringTopic() {
+ $this->setExpectedException('\Ratchet\Wamp\Exception');
+
+ $conn = new WampConnection($this->newConn());
+ $this->_comp->onOpen($conn);
+
+ $this->_comp->onMessage($conn, json_encode([1, ['hells', 'nope'], ['bad', 'input']]));
+ }
+
+ public function testBadPublishWithNonStringTopic() {
+ $this->setExpectedException('\Ratchet\Wamp\Exception');
+
+ $conn = new WampConnection($this->newConn());
+ $this->_comp->onOpen($conn);
+
+ $this->_comp->onMessage($conn, json_encode([7, ['bad', 'input'], 'Hider']));
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/unit/Wamp/TopicManagerTest.php b/assets/php/vendor/cboden/ratchet/tests/unit/Wamp/TopicManagerTest.php
new file mode 100644
index 0000000..b21b6bc
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/unit/Wamp/TopicManagerTest.php
@@ -0,0 +1,226 @@
+<?php
+namespace Ratchet\Wamp;
+
+/**
+ * @covers Ratchet\Wamp\TopicManager
+ */
+class TopicManagerTest extends \PHPUnit_Framework_TestCase {
+ private $mock;
+
+ /**
+ * @var \Ratchet\Wamp\TopicManager
+ */
+ private $mngr;
+
+ /**
+ * @var \Ratchet\ConnectionInterface
+ */
+ private $conn;
+
+ public function setUp() {
+ $this->conn = $this->getMock('\Ratchet\ConnectionInterface');
+ $this->mock = $this->getMock('\Ratchet\Wamp\WampServerInterface');
+ $this->mngr = new TopicManager($this->mock);
+
+ $this->conn->WAMP = new \StdClass;
+ $this->mngr->onOpen($this->conn);
+ }
+
+ public function testGetTopicReturnsTopicObject() {
+ $class = new \ReflectionClass('Ratchet\Wamp\TopicManager');
+ $method = $class->getMethod('getTopic');
+ $method->setAccessible(true);
+
+ $topic = $method->invokeArgs($this->mngr, array('The Topic'));
+
+ $this->assertInstanceOf('Ratchet\Wamp\Topic', $topic);
+ }
+
+ public function testGetTopicCreatesTopicWithSameName() {
+ $name = 'The Topic';
+
+ $class = new \ReflectionClass('Ratchet\Wamp\TopicManager');
+ $method = $class->getMethod('getTopic');
+ $method->setAccessible(true);
+
+ $topic = $method->invokeArgs($this->mngr, array($name));
+
+ $this->assertEquals($name, $topic->getId());
+ }
+
+ public function testGetTopicReturnsSameObject() {
+ $class = new \ReflectionClass('Ratchet\Wamp\TopicManager');
+ $method = $class->getMethod('getTopic');
+ $method->setAccessible(true);
+
+ $topic = $method->invokeArgs($this->mngr, array('No copy'));
+ $again = $method->invokeArgs($this->mngr, array('No copy'));
+
+ $this->assertSame($topic, $again);
+ }
+
+ public function testOnOpen() {
+ $this->mock->expects($this->once())->method('onOpen');
+ $this->mngr->onOpen($this->conn);
+ }
+
+ public function testOnCall() {
+ $id = uniqid();
+
+ $this->mock->expects($this->once())->method('onCall')->with(
+ $this->conn
+ , $id
+ , $this->isInstanceOf('Ratchet\Wamp\Topic')
+ , array()
+ );
+
+ $this->mngr->onCall($this->conn, $id, 'new topic', array());
+ }
+
+ public function testOnSubscribeCreatesTopicObject() {
+ $this->mock->expects($this->once())->method('onSubscribe')->with(
+ $this->conn, $this->isInstanceOf('Ratchet\Wamp\Topic')
+ );
+
+ $this->mngr->onSubscribe($this->conn, 'new topic');
+ }
+
+ public function testTopicIsInConnectionOnSubscribe() {
+ $name = 'New Topic';
+
+ $class = new \ReflectionClass('Ratchet\Wamp\TopicManager');
+ $method = $class->getMethod('getTopic');
+ $method->setAccessible(true);
+
+ $topic = $method->invokeArgs($this->mngr, array($name));
+
+ $this->mngr->onSubscribe($this->conn, $name);
+
+ $this->assertTrue($this->conn->WAMP->subscriptions->contains($topic));
+ }
+
+ public function testDoubleSubscriptionFiresOnce() {
+ $this->mock->expects($this->exactly(1))->method('onSubscribe');
+
+ $this->mngr->onSubscribe($this->conn, 'same topic');
+ $this->mngr->onSubscribe($this->conn, 'same topic');
+ }
+
+ public function testUnsubscribeEvent() {
+ $name = 'in and out';
+ $this->mock->expects($this->once())->method('onUnsubscribe')->with(
+ $this->conn, $this->isInstanceOf('Ratchet\Wamp\Topic')
+ );
+
+ $this->mngr->onSubscribe($this->conn, $name);
+ $this->mngr->onUnsubscribe($this->conn, $name);
+ }
+
+ public function testUnsubscribeFiresOnce() {
+ $name = 'getting sleepy';
+ $this->mock->expects($this->exactly(1))->method('onUnsubscribe');
+
+ $this->mngr->onSubscribe($this->conn, $name);
+ $this->mngr->onUnsubscribe($this->conn, $name);
+ $this->mngr->onUnsubscribe($this->conn, $name);
+ }
+
+ public function testUnsubscribeRemovesTopicFromConnection() {
+ $name = 'Bye Bye Topic';
+
+ $class = new \ReflectionClass('Ratchet\Wamp\TopicManager');
+ $method = $class->getMethod('getTopic');
+ $method->setAccessible(true);
+
+ $topic = $method->invokeArgs($this->mngr, array($name));
+
+ $this->mngr->onSubscribe($this->conn, $name);
+ $this->mngr->onUnsubscribe($this->conn, $name);
+
+ $this->assertFalse($this->conn->WAMP->subscriptions->contains($topic));
+ }
+
+ public function testOnPublishBubbles() {
+ $msg = 'Cover all the code!';
+
+ $this->mock->expects($this->once())->method('onPublish')->with(
+ $this->conn
+ , $this->isInstanceOf('Ratchet\Wamp\Topic')
+ , $msg
+ , $this->isType('array')
+ , $this->isType('array')
+ );
+
+ $this->mngr->onPublish($this->conn, 'topic coverage', $msg, array(), array());
+ }
+
+ public function testOnCloseBubbles() {
+ $this->mock->expects($this->once())->method('onClose')->with($this->conn);
+ $this->mngr->onClose($this->conn);
+ }
+
+ protected function topicProvider($name) {
+ $class = new \ReflectionClass('Ratchet\Wamp\TopicManager');
+ $method = $class->getMethod('getTopic');
+ $method->setAccessible(true);
+
+ $attribute = $class->getProperty('topicLookup');
+ $attribute->setAccessible(true);
+
+ $topic = $method->invokeArgs($this->mngr, array($name));
+
+ return array($topic, $attribute);
+ }
+
+ public function testConnIsRemovedFromTopicOnClose() {
+ $name = 'State Testing';
+ list($topic, $attribute) = $this->topicProvider($name);
+
+ $this->assertCount(1, $attribute->getValue($this->mngr));
+
+ $this->mngr->onSubscribe($this->conn, $name);
+ $this->mngr->onClose($this->conn);
+
+ $this->assertFalse($topic->has($this->conn));
+ }
+
+ public static function topicConnExpectationProvider() {
+ return [
+ [ 'onClose', 0]
+ , ['onUnsubscribe', 0]
+ ];
+ }
+
+ /**
+ * @dataProvider topicConnExpectationProvider
+ */
+ public function testTopicRetentionFromLeavingConnections($methodCall, $expectation) {
+ $topicName = 'checkTopic';
+ list($topic, $attribute) = $this->topicProvider($topicName);
+
+ $this->mngr->onSubscribe($this->conn, $topicName);
+ call_user_func_array(array($this->mngr, $methodCall), array($this->conn, $topicName));
+
+ $this->assertCount($expectation, $attribute->getValue($this->mngr));
+ }
+
+ public function testOnErrorBubbles() {
+ $e = new \Exception('All work and no play makes Chris a dull boy');
+ $this->mock->expects($this->once())->method('onError')->with($this->conn, $e);
+
+ $this->mngr->onError($this->conn, $e);
+ }
+
+ public function testGetSubProtocolsReturnsArray() {
+ $this->assertInternalType('array', $this->mngr->getSubProtocols());
+ }
+
+ public function testGetSubProtocolsBubbles() {
+ $subs = array('hello', 'world');
+ $app = $this->getMock('Ratchet\Wamp\Stub\WsWampServerInterface');
+ $app->expects($this->once())->method('getSubProtocols')->will($this->returnValue($subs));
+ $mngr = new TopicManager($app);
+
+ $this->assertEquals($subs, $mngr->getSubProtocols());
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/unit/Wamp/TopicTest.php b/assets/php/vendor/cboden/ratchet/tests/unit/Wamp/TopicTest.php
new file mode 100644
index 0000000..b8685b7
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/unit/Wamp/TopicTest.php
@@ -0,0 +1,164 @@
+<?php
+namespace Ratchet\Wamp;
+
+/**
+ * @covers Ratchet\Wamp\Topic
+ */
+class TopicTest extends \PHPUnit_Framework_TestCase {
+ public function testGetId() {
+ $id = uniqid();
+ $topic = new Topic($id);
+
+ $this->assertEquals($id, $topic->getId());
+ }
+
+ public function testAddAndCount() {
+ $topic = new Topic('merp');
+
+ $topic->add($this->newConn());
+ $topic->add($this->newConn());
+ $topic->add($this->newConn());
+
+ $this->assertEquals(3, count($topic));
+ }
+
+ public function testRemove() {
+ $topic = new Topic('boop');
+ $tracked = $this->newConn();
+
+ $topic->add($this->newConn());
+ $topic->add($tracked);
+ $topic->add($this->newConn());
+
+ $topic->remove($tracked);
+
+ $this->assertEquals(2, count($topic));
+ }
+
+ public function testBroadcast() {
+ $msg = 'Hello World!';
+ $name = 'Batman';
+ $protocol = json_encode(array(8, $name, $msg));
+
+ $first = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface')));
+ $second = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface')));
+
+ $first->expects($this->once())
+ ->method('send')
+ ->with($this->equalTo($protocol));
+
+ $second->expects($this->once())
+ ->method('send')
+ ->with($this->equalTo($protocol));
+
+ $topic = new Topic($name);
+ $topic->add($first);
+ $topic->add($second);
+
+ $topic->broadcast($msg);
+ }
+
+ public function testBroadcastWithExclude() {
+ $msg = 'Hello odd numbers';
+ $name = 'Excluding';
+ $protocol = json_encode(array(8, $name, $msg));
+
+ $first = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface')));
+ $second = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface')));
+ $third = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface')));
+
+ $first->expects($this->once())
+ ->method('send')
+ ->with($this->equalTo($protocol));
+
+ $second->expects($this->never())->method('send');
+
+ $third->expects($this->once())
+ ->method('send')
+ ->with($this->equalTo($protocol));
+
+ $topic = new Topic($name);
+ $topic->add($first);
+ $topic->add($second);
+ $topic->add($third);
+
+ $topic->broadcast($msg, array($second->WAMP->sessionId));
+ }
+
+ public function testBroadcastWithEligible() {
+ $msg = 'Hello white list';
+ $name = 'Eligible';
+ $protocol = json_encode(array(8, $name, $msg));
+
+ $first = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface')));
+ $second = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface')));
+ $third = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface')));
+
+ $first->expects($this->once())
+ ->method('send')
+ ->with($this->equalTo($protocol));
+
+ $second->expects($this->never())->method('send');
+
+ $third->expects($this->once())
+ ->method('send')
+ ->with($this->equalTo($protocol));
+
+ $topic = new Topic($name);
+ $topic->add($first);
+ $topic->add($second);
+ $topic->add($third);
+
+ $topic->broadcast($msg, array(), array($first->WAMP->sessionId, $third->WAMP->sessionId));
+ }
+
+ public function testIterator() {
+ $first = $this->newConn();
+ $second = $this->newConn();
+ $third = $this->newConn();
+
+ $topic = new Topic('Joker');
+ $topic->add($first)->add($second)->add($third);
+
+ $check = array($first, $second, $third);
+
+ foreach ($topic as $mock) {
+ $this->assertNotSame(false, array_search($mock, $check));
+ }
+ }
+
+ public function testToString() {
+ $name = 'Bane';
+ $topic = new Topic($name);
+
+ $this->assertEquals($name, (string)$topic);
+ }
+
+ public function testDoesHave() {
+ $conn = $this->newConn();
+ $topic = new Topic('Two Face');
+ $topic->add($conn);
+
+ $this->assertTrue($topic->has($conn));
+ }
+
+ public function testDoesNotHave() {
+ $conn = $this->newConn();
+ $topic = new Topic('Alfred');
+
+ $this->assertFalse($topic->has($conn));
+ }
+
+ public function testDoesNotHaveAfterRemove() {
+ $conn = $this->newConn();
+ $topic = new Topic('Ras');
+
+ $topic->add($conn)->remove($conn);
+
+ $this->assertFalse($topic->has($conn));
+ }
+
+ protected function newConn() {
+ return new WampConnection($this->getMock('\\Ratchet\\ConnectionInterface'));
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/unit/Wamp/WampConnectionTest.php b/assets/php/vendor/cboden/ratchet/tests/unit/Wamp/WampConnectionTest.php
new file mode 100644
index 0000000..adf59d5
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/unit/Wamp/WampConnectionTest.php
@@ -0,0 +1,77 @@
+<?php
+namespace Ratchet\Wamp;
+
+/**
+ * @covers Ratchet\Wamp\WampConnection
+ */
+class WampConnectionTest extends \PHPUnit_Framework_TestCase {
+ protected $conn;
+ protected $mock;
+
+ public function setUp() {
+ $this->mock = $this->getMock('\\Ratchet\\ConnectionInterface');
+ $this->conn = new WampConnection($this->mock);
+ }
+
+ public function testCallResult() {
+ $callId = uniqid();
+ $data = array('hello' => 'world', 'herp' => 'derp');
+
+ $this->mock->expects($this->once())->method('send')->with(json_encode(array(3, $callId, $data)));
+
+ $this->conn->callResult($callId, $data);
+ }
+
+ public function testCallError() {
+ $callId = uniqid();
+ $uri = 'http://example.com/end/point';
+
+ $this->mock->expects($this->once())->method('send')->with(json_encode(array(4, $callId, $uri, '')));
+
+ $this->conn->callError($callId, $uri);
+ }
+
+ public function testCallErrorWithTopic() {
+ $callId = uniqid();
+ $uri = 'http://example.com/end/point';
+
+ $this->mock->expects($this->once())->method('send')->with(json_encode(array(4, $callId, $uri, '')));
+
+ $this->conn->callError($callId, new Topic($uri));
+ }
+
+ public function testDetailedCallError() {
+ $callId = uniqid();
+ $uri = 'http://example.com/end/point';
+ $desc = 'beep boop beep';
+ $detail = 'Error: Too much awesome';
+
+ $this->mock->expects($this->once())->method('send')->with(json_encode(array(4, $callId, $uri, $desc, $detail)));
+
+ $this->conn->callError($callId, $uri, $desc, $detail);
+ }
+
+ public function testPrefix() {
+ $shortOut = 'outgoing';
+ $longOut = 'http://example.com/outgoing';
+
+ $this->mock->expects($this->once())->method('send')->with(json_encode(array(1, $shortOut, $longOut)));
+
+ $this->conn->prefix($shortOut, $longOut);
+ }
+
+ public function testGetUriWhenNoCurieGiven() {
+ $uri = 'http://example.com/noshort';
+
+ $this->assertEquals($uri, $this->conn->getUri($uri));
+ }
+
+ public function testClose() {
+ $mock = $this->getMock('\\Ratchet\\ConnectionInterface');
+ $conn = new WampConnection($mock);
+
+ $mock->expects($this->once())->method('close');
+
+ $conn->close();
+ }
+}
diff --git a/assets/php/vendor/cboden/ratchet/tests/unit/Wamp/WampServerTest.php b/assets/php/vendor/cboden/ratchet/tests/unit/Wamp/WampServerTest.php
new file mode 100644
index 0000000..626b1ce
--- /dev/null
+++ b/assets/php/vendor/cboden/ratchet/tests/unit/Wamp/WampServerTest.php
@@ -0,0 +1,49 @@
+<?php
+namespace Ratchet\Wamp;
+use Ratchet\AbstractMessageComponentTestCase;
+
+/**
+ * @covers Ratchet\Wamp\WampServer
+ */
+class WampServerTest extends AbstractMessageComponentTestCase {
+ public function getConnectionClassString() {
+ return '\Ratchet\Wamp\WampConnection';
+ }
+
+ public function getDecoratorClassString() {
+ return 'Ratchet\Wamp\WampServer';
+ }
+
+ public function getComponentClassString() {
+ return '\Ratchet\Wamp\WampServerInterface';
+ }
+
+ public function testOnMessageToEvent() {
+ $published = 'Client published this message';
+
+ $this->_app->expects($this->once())->method('onPublish')->with(
+ $this->isExpectedConnection()
+ , new \PHPUnit_Framework_Constraint_IsInstanceOf('\Ratchet\Wamp\Topic')
+ , $published
+ , array()
+ , array()
+ );
+
+ $this->_serv->onMessage($this->_conn, json_encode(array(7, 'topic', $published)));
+ }
+
+ public function testGetSubProtocols() {
+ // todo: could expand on this
+ $this->assertInternalType('array', $this->_serv->getSubProtocols());
+ }
+
+ public function testConnectionClosesOnInvalidJson() {
+ $this->_conn->expects($this->once())->method('close');
+ $this->_serv->onMessage($this->_conn, 'invalid json');
+ }
+
+ public function testConnectionClosesOnProtocolError() {
+ $this->_conn->expects($this->once())->method('close');
+ $this->_serv->onMessage($this->_conn, json_encode(array('valid' => 'json', 'invalid' => 'protocol')));
+ }
+}