From: Diogo Cordeiro Date: Tue, 25 Jun 2019 09:35:31 +0000 (+0100) Subject: [CORE][COMPOSER] Add hoa/consistency X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=ec32db2dd6fd00ede0741df117995080cb64da38;p=quix0rs-gnu-social.git [CORE][COMPOSER] Add hoa/consistency Renamed curry to callable_left_curry --- diff --git a/composer.json b/composer.json index 3c4eb61eb7..11773a74ff 100644 --- a/composer.json +++ b/composer.json @@ -19,6 +19,7 @@ "apereo/phpcas": "^1.3", "diogocomposer/xmpphp": "^3.0", "ezyang/htmlpurifier": "^4.10", + "hoa/consistency": "^1.17.05.02", "masterminds/html5": "^2.6", "mf2/mf2": "^0.4.6", "michelf/php-markdown": "^1.8.0", diff --git a/composer.lock b/composer.lock index 670b7973a9..5d4ab05e8f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ac49a57ede587e949b9bad4b3c080a1d", + "content-hash": "1f145be7e041fab248e0ffa15684f12f", "packages": [ { "name": "apereo/phpcas", @@ -179,6 +179,179 @@ ], "time": "2018-02-23T01:58:20+00:00" }, + { + "name": "hoa/consistency", + "version": "1.17.05.02", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Consistency.git", + "reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Consistency/zipball/fd7d0adc82410507f332516faf655b6ed22e4c2f", + "reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f", + "shasum": "" + }, + "require": { + "hoa/exception": "~1.0", + "php": ">=5.5.0" + }, + "require-dev": { + "hoa/stream": "~1.0", + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Consistency\\": "." + }, + "files": [ + "Prelude.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Consistency library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "autoloader", + "callable", + "consistency", + "entity", + "flex", + "keyword", + "library" + ], + "time": "2017-05-02T12:18:12+00:00" + }, + { + "name": "hoa/event", + "version": "1.17.01.13", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Event.git", + "reference": "6c0060dced212ffa3af0e34bb46624f990b29c54" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Event/zipball/6c0060dced212ffa3af0e34bb46624f990b29c54", + "reference": "6c0060dced212ffa3af0e34bb46624f990b29c54", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Event\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Event library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "event", + "library", + "listener", + "observer" + ], + "time": "2017-01-13T15:30:50+00:00" + }, + { + "name": "hoa/exception", + "version": "1.17.01.16", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Exception.git", + "reference": "091727d46420a3d7468ef0595651488bfc3a458f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Exception/zipball/091727d46420a3d7468ef0595651488bfc3a458f", + "reference": "091727d46420a3d7468ef0595651488bfc3a458f", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/event": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Exception\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Exception library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "exception", + "library" + ], + "time": "2017-01-16T07:53:27+00:00" + }, { "name": "masterminds/html5", "version": "2.6.0", @@ -1277,179 +1450,6 @@ ], "time": "2017-08-08T07:44:07+00:00" }, - { - "name": "hoa/consistency", - "version": "1.17.05.02", - "source": { - "type": "git", - "url": "https://github.com/hoaproject/Consistency.git", - "reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/hoaproject/Consistency/zipball/fd7d0adc82410507f332516faf655b6ed22e4c2f", - "reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f", - "shasum": "" - }, - "require": { - "hoa/exception": "~1.0", - "php": ">=5.5.0" - }, - "require-dev": { - "hoa/stream": "~1.0", - "hoa/test": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Hoa\\Consistency\\": "." - }, - "files": [ - "Prelude.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Ivan Enderlin", - "email": "ivan.enderlin@hoa-project.net" - }, - { - "name": "Hoa community", - "homepage": "https://hoa-project.net/" - } - ], - "description": "The Hoa\\Consistency library.", - "homepage": "https://hoa-project.net/", - "keywords": [ - "autoloader", - "callable", - "consistency", - "entity", - "flex", - "keyword", - "library" - ], - "time": "2017-05-02T12:18:12+00:00" - }, - { - "name": "hoa/event", - "version": "1.17.01.13", - "source": { - "type": "git", - "url": "https://github.com/hoaproject/Event.git", - "reference": "6c0060dced212ffa3af0e34bb46624f990b29c54" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/hoaproject/Event/zipball/6c0060dced212ffa3af0e34bb46624f990b29c54", - "reference": "6c0060dced212ffa3af0e34bb46624f990b29c54", - "shasum": "" - }, - "require": { - "hoa/consistency": "~1.0", - "hoa/exception": "~1.0" - }, - "require-dev": { - "hoa/test": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Hoa\\Event\\": "." - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Ivan Enderlin", - "email": "ivan.enderlin@hoa-project.net" - }, - { - "name": "Hoa community", - "homepage": "https://hoa-project.net/" - } - ], - "description": "The Hoa\\Event library.", - "homepage": "https://hoa-project.net/", - "keywords": [ - "event", - "library", - "listener", - "observer" - ], - "time": "2017-01-13T15:30:50+00:00" - }, - { - "name": "hoa/exception", - "version": "1.17.01.16", - "source": { - "type": "git", - "url": "https://github.com/hoaproject/Exception.git", - "reference": "091727d46420a3d7468ef0595651488bfc3a458f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/hoaproject/Exception/zipball/091727d46420a3d7468ef0595651488bfc3a458f", - "reference": "091727d46420a3d7468ef0595651488bfc3a458f", - "shasum": "" - }, - "require": { - "hoa/consistency": "~1.0", - "hoa/event": "~1.0" - }, - "require-dev": { - "hoa/test": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Hoa\\Exception\\": "." - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Ivan Enderlin", - "email": "ivan.enderlin@hoa-project.net" - }, - { - "name": "Hoa community", - "homepage": "https://hoa-project.net/" - } - ], - "description": "The Hoa\\Exception library.", - "homepage": "https://hoa-project.net/", - "keywords": [ - "exception", - "library" - ], - "time": "2017-01-16T07:53:27+00:00" - }, { "name": "hoa/file", "version": "1.17.07.11", diff --git a/lib/callable_left_curry.php b/lib/callable_left_curry.php new file mode 100644 index 0000000000..37c9c1c18e --- /dev/null +++ b/lib/callable_left_curry.php @@ -0,0 +1,36 @@ +. + */ + +/** + * PHP 5.3 implementation of function currying, using native closures. + * On 5.2 and lower we use the fallback implementation in util.php + * + * @param callback $fn + * @param ... any remaining arguments will be appended to call-time params + * @return callback + */ +function callable_left_curry($fn) { + $extra_args = func_get_args(); + array_shift($extra_args); + return function() use ($fn, $extra_args) { + $args = func_get_args(); + return call_user_func_array($fn, + array_merge($args, $extra_args)); + }; +} diff --git a/lib/curry.php b/lib/curry.php deleted file mode 100644 index 6136dcdc37..0000000000 --- a/lib/curry.php +++ /dev/null @@ -1,36 +0,0 @@ -. - */ - -/** - * PHP 5.3 implementation of function currying, using native closures. - * On 5.2 and lower we use the fallback implementation in util.php - * - * @param callback $fn - * @param ... any remaining arguments will be appended to call-time params - * @return callback - */ -function curry($fn) { - $extra_args = func_get_args(); - array_shift($extra_args); - return function() use ($fn, $extra_args) { - $args = func_get_args(); - return call_user_func_array($fn, - array_merge($args, $extra_args)); - }; -} diff --git a/lib/util.php b/lib/util.php index 28d7bba3ed..0866b32d55 100644 --- a/lib/util.php +++ b/lib/util.php @@ -927,7 +927,7 @@ define('_URL_SCHEME_SINGLE_COLON', 2); define('_URL_SCHEME_NO_DOMAIN', 4); define('_URL_SCHEME_COLON_COORDINATES', 8); -function common_url_schemes($filter=null) +function common_url_schemes($filter = null) { // TODO: move these to $config $schemes = ['http' => _URL_SCHEME_COLON_DOUBLE_SLASH, @@ -1040,7 +1040,7 @@ function common_replace_urls_callback($text, $callback, $arg = null) '#ixu'; //preg_match_all($regex,$text,$matches); //print_r($matches); - return preg_replace_callback($regex, curry('callback_helper', $callback, $arg), $text); + return preg_replace_callback($regex, callable_left_curry('callback_helper', $callback, $arg), $text); } /** @@ -1054,11 +1054,11 @@ function common_replace_urls_callback($text, $callback, $arg = null) * * @access private */ -function callback_helper($matches, $callback, $arg=null) +function callback_helper($matches, $callback, $arg = null) { - $url=$matches[1]; + $url = $matches[1]; $left = strpos($matches[0], $url); - $right = $left+strlen($url); + $right = $left + strlen($url); $groupSymbolSets=[ [ @@ -1078,31 +1078,31 @@ function callback_helper($matches, $callback, $arg=null) 'right'=>'>' ] ]; - $cannotEndWith=['.','?',',','#']; - $original_url=$url; + + $cannotEndWith = ['.','?',',','#']; do { - $original_url=$url; + $original_url = $url; foreach ($groupSymbolSets as $groupSymbolSet) { - if (substr($url, -1)==$groupSymbolSet['right']) { + if (substr($url, -1) == $groupSymbolSet['right']) { $group_left_count = substr_count($url, $groupSymbolSet['left']); $group_right_count = substr_count($url, $groupSymbolSet['right']); - if ($group_left_count<$group_right_count) { - $right-=1; - $url=substr($url, 0, -1); + if ($group_left_count < $group_right_count) { + $right -= 1; + $url = substr($url, 0, -1); } } } if (in_array(substr($url, -1), $cannotEndWith)) { - $right-=1; + $right -= 1; $url=substr($url, 0, -1); } - } while ($original_url!=$url); + } while ($original_url != $url); $result = call_user_func_array($callback, [$url, $arg]); return substr($matches[0], 0, $left) . $result . substr($matches[0], $right); } -require_once INSTALLDIR . "/lib/curry.php"; +require_once INSTALLDIR . "/lib/callable_left_curry.php"; function common_linkify($url) { diff --git a/tests/CurryTest.php b/tests/CurryTest.php index 6e776e41b4..2722a54fc5 100644 --- a/tests/CurryTest.php +++ b/tests/CurryTest.php @@ -20,7 +20,7 @@ class CurryTest extends PHPUnit_Framework_TestCase public function testProduction($callback, $curry_params, $call_params, $expected) { $params = array_merge(array($callback), $curry_params); - $curried = call_user_func_array('curry', $params); + $curried = call_user_func_array('callable_left_curry', $params); $result = call_user_func_array($curried, $call_params); $this->assertEquals($expected, $result); } diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 8afc77cf8e..cbd741d8aa 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -379,6 +379,37 @@ return array( 'HTMLPurifier_VarParser_Flexible' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Flexible.php', 'HTMLPurifier_VarParser_Native' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Native.php', 'HTMLPurifier_Zipper' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Zipper.php', + 'Hoa\\Consistency\\Autoloader' => $vendorDir . '/hoa/consistency/Autoloader.php', + 'Hoa\\Consistency\\Consistency' => $vendorDir . '/hoa/consistency/Consistency.php', + 'Hoa\\Consistency\\Exception' => $vendorDir . '/hoa/consistency/Exception.php', + 'Hoa\\Consistency\\Test\\Unit\\Autoloader' => $vendorDir . '/hoa/consistency/Test/Unit/Autoloader.php', + 'Hoa\\Consistency\\Test\\Unit\\Consistency' => $vendorDir . '/hoa/consistency/Test/Unit/Consistency.php', + 'Hoa\\Consistency\\Test\\Unit\\Exception' => $vendorDir . '/hoa/consistency/Test/Unit/Exception.php', + 'Hoa\\Consistency\\Test\\Unit\\Xcallable' => $vendorDir . '/hoa/consistency/Test/Unit/Xcallable.php', + 'Hoa\\Consistency\\Xcallable' => $vendorDir . '/hoa/consistency/Xcallable.php', + 'Hoa\\Event\\Bucket' => $vendorDir . '/hoa/event/Bucket.php', + 'Hoa\\Event\\Event' => $vendorDir . '/hoa/event/Event.php', + 'Hoa\\Event\\Exception' => $vendorDir . '/hoa/event/Exception.php', + 'Hoa\\Event\\Listenable' => $vendorDir . '/hoa/event/Listenable.php', + 'Hoa\\Event\\Listener' => $vendorDir . '/hoa/event/Listener.php', + 'Hoa\\Event\\Listens' => $vendorDir . '/hoa/event/Listens.php', + 'Hoa\\Event\\Source' => $vendorDir . '/hoa/event/Source.php', + 'Hoa\\Event\\Test\\Unit\\Bucket' => $vendorDir . '/hoa/event/Test/Unit/Bucket.php', + 'Hoa\\Event\\Test\\Unit\\Event' => $vendorDir . '/hoa/event/Test/Unit/Event.php', + 'Hoa\\Event\\Test\\Unit\\Exception' => $vendorDir . '/hoa/event/Test/Unit/Exception.php', + 'Hoa\\Event\\Test\\Unit\\Listenable' => $vendorDir . '/hoa/event/Test/Unit/Listenable.php', + 'Hoa\\Event\\Test\\Unit\\Listener' => $vendorDir . '/hoa/event/Test/Unit/Listener.php', + 'Hoa\\Event\\Test\\Unit\\Listens' => $vendorDir . '/hoa/event/Test/Unit/Listens.php', + 'Hoa\\Event\\Test\\Unit\\Source' => $vendorDir . '/hoa/event/Test/Unit/Source.php', + 'Hoa\\Event\\Test\\Unit\\_Listenable' => $vendorDir . '/hoa/event/Test/Unit/Listens.php', + 'Hoa\\Exception\\Error' => $vendorDir . '/hoa/exception/Error.php', + 'Hoa\\Exception\\Exception' => $vendorDir . '/hoa/exception/Exception.php', + 'Hoa\\Exception\\Group' => $vendorDir . '/hoa/exception/Group.php', + 'Hoa\\Exception\\Idle' => $vendorDir . '/hoa/exception/Idle.php', + 'Hoa\\Exception\\Test\\Unit\\Error' => $vendorDir . '/hoa/exception/Test/Unit/Error.php', + 'Hoa\\Exception\\Test\\Unit\\Exception' => $vendorDir . '/hoa/exception/Test/Unit/Exception.php', + 'Hoa\\Exception\\Test\\Unit\\Group' => $vendorDir . '/hoa/exception/Test/Unit/Group.php', + 'Hoa\\Exception\\Test\\Unit\\Idle' => $vendorDir . '/hoa/exception/Test/Unit/Idle.php', 'Masterminds\\HTML5' => $vendorDir . '/masterminds/html5/src/HTML5.php', 'Masterminds\\HTML5\\Elements' => $vendorDir . '/masterminds/html5/src/HTML5/Elements.php', 'Masterminds\\HTML5\\Entities' => $vendorDir . '/masterminds/html5/src/HTML5/Entities.php', diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php index 0698628c17..d7eeeb8bbc 100644 --- a/vendor/composer/autoload_files.php +++ b/vendor/composer/autoload_files.php @@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( + 'e88992873b7765f9b5710cab95ba5dd7' => $vendorDir . '/hoa/consistency/Prelude.php', '5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php', '2cffec82183ee1cea088009cef9a6fc3' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php', '757772e28a0943a9afe83def8db95bdf' => $vendorDir . '/mf2/mf2/Mf2/Parser.php', diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index de5192bb91..14af1954fb 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -12,4 +12,7 @@ return array( 'ParagonIE\\ConstantTime\\' => array($vendorDir . '/paragonie/constant_time_encoding/src'), 'Michelf\\' => array($vendorDir . '/michelf/php-markdown/Michelf'), 'Masterminds\\' => array($vendorDir . '/masterminds/html5/src'), + 'Hoa\\Exception\\' => array($vendorDir . '/hoa/exception'), + 'Hoa\\Event\\' => array($vendorDir . '/hoa/event'), + 'Hoa\\Consistency\\' => array($vendorDir . '/hoa/consistency'), ); diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index d560ecb13b..4f55871647 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -7,6 +7,7 @@ namespace Composer\Autoload; class ComposerStaticInit444c3f31864f68a3f466e2c19837e185 { public static $files = array ( + 'e88992873b7765f9b5710cab95ba5dd7' => __DIR__ . '/..' . '/hoa/consistency/Prelude.php', '5255c38a0faeba867671b61dfda6d864' => __DIR__ . '/..' . '/paragonie/random_compat/lib/random.php', '2cffec82183ee1cea088009cef9a6fc3' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php', '757772e28a0943a9afe83def8db95bdf' => __DIR__ . '/..' . '/mf2/mf2/Mf2/Parser.php', @@ -35,6 +36,12 @@ class ComposerStaticInit444c3f31864f68a3f466e2c19837e185 'Michelf\\' => 8, 'Masterminds\\' => 12, ), + 'H' => + array ( + 'Hoa\\Exception\\' => 14, + 'Hoa\\Event\\' => 10, + 'Hoa\\Consistency\\' => 16, + ), ); public static $prefixDirsPsr4 = array ( @@ -62,6 +69,18 @@ class ComposerStaticInit444c3f31864f68a3f466e2c19837e185 array ( 0 => __DIR__ . '/..' . '/masterminds/html5/src', ), + 'Hoa\\Exception\\' => + array ( + 0 => __DIR__ . '/..' . '/hoa/exception', + ), + 'Hoa\\Event\\' => + array ( + 0 => __DIR__ . '/..' . '/hoa/event', + ), + 'Hoa\\Consistency\\' => + array ( + 0 => __DIR__ . '/..' . '/hoa/consistency', + ), ); public static $prefixesPsr0 = array ( @@ -448,6 +467,37 @@ class ComposerStaticInit444c3f31864f68a3f466e2c19837e185 'HTMLPurifier_VarParser_Flexible' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Flexible.php', 'HTMLPurifier_VarParser_Native' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Native.php', 'HTMLPurifier_Zipper' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Zipper.php', + 'Hoa\\Consistency\\Autoloader' => __DIR__ . '/..' . '/hoa/consistency/Autoloader.php', + 'Hoa\\Consistency\\Consistency' => __DIR__ . '/..' . '/hoa/consistency/Consistency.php', + 'Hoa\\Consistency\\Exception' => __DIR__ . '/..' . '/hoa/consistency/Exception.php', + 'Hoa\\Consistency\\Test\\Unit\\Autoloader' => __DIR__ . '/..' . '/hoa/consistency/Test/Unit/Autoloader.php', + 'Hoa\\Consistency\\Test\\Unit\\Consistency' => __DIR__ . '/..' . '/hoa/consistency/Test/Unit/Consistency.php', + 'Hoa\\Consistency\\Test\\Unit\\Exception' => __DIR__ . '/..' . '/hoa/consistency/Test/Unit/Exception.php', + 'Hoa\\Consistency\\Test\\Unit\\Xcallable' => __DIR__ . '/..' . '/hoa/consistency/Test/Unit/Xcallable.php', + 'Hoa\\Consistency\\Xcallable' => __DIR__ . '/..' . '/hoa/consistency/Xcallable.php', + 'Hoa\\Event\\Bucket' => __DIR__ . '/..' . '/hoa/event/Bucket.php', + 'Hoa\\Event\\Event' => __DIR__ . '/..' . '/hoa/event/Event.php', + 'Hoa\\Event\\Exception' => __DIR__ . '/..' . '/hoa/event/Exception.php', + 'Hoa\\Event\\Listenable' => __DIR__ . '/..' . '/hoa/event/Listenable.php', + 'Hoa\\Event\\Listener' => __DIR__ . '/..' . '/hoa/event/Listener.php', + 'Hoa\\Event\\Listens' => __DIR__ . '/..' . '/hoa/event/Listens.php', + 'Hoa\\Event\\Source' => __DIR__ . '/..' . '/hoa/event/Source.php', + 'Hoa\\Event\\Test\\Unit\\Bucket' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Bucket.php', + 'Hoa\\Event\\Test\\Unit\\Event' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Event.php', + 'Hoa\\Event\\Test\\Unit\\Exception' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Exception.php', + 'Hoa\\Event\\Test\\Unit\\Listenable' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Listenable.php', + 'Hoa\\Event\\Test\\Unit\\Listener' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Listener.php', + 'Hoa\\Event\\Test\\Unit\\Listens' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Listens.php', + 'Hoa\\Event\\Test\\Unit\\Source' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Source.php', + 'Hoa\\Event\\Test\\Unit\\_Listenable' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Listens.php', + 'Hoa\\Exception\\Error' => __DIR__ . '/..' . '/hoa/exception/Error.php', + 'Hoa\\Exception\\Exception' => __DIR__ . '/..' . '/hoa/exception/Exception.php', + 'Hoa\\Exception\\Group' => __DIR__ . '/..' . '/hoa/exception/Group.php', + 'Hoa\\Exception\\Idle' => __DIR__ . '/..' . '/hoa/exception/Idle.php', + 'Hoa\\Exception\\Test\\Unit\\Error' => __DIR__ . '/..' . '/hoa/exception/Test/Unit/Error.php', + 'Hoa\\Exception\\Test\\Unit\\Exception' => __DIR__ . '/..' . '/hoa/exception/Test/Unit/Exception.php', + 'Hoa\\Exception\\Test\\Unit\\Group' => __DIR__ . '/..' . '/hoa/exception/Test/Unit/Group.php', + 'Hoa\\Exception\\Test\\Unit\\Idle' => __DIR__ . '/..' . '/hoa/exception/Test/Unit/Idle.php', 'Masterminds\\HTML5' => __DIR__ . '/..' . '/masterminds/html5/src/HTML5.php', 'Masterminds\\HTML5\\Elements' => __DIR__ . '/..' . '/masterminds/html5/src/HTML5/Elements.php', 'Masterminds\\HTML5\\Entities' => __DIR__ . '/..' . '/masterminds/html5/src/HTML5/Entities.php', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 34b0a044c4..e47ff3faed 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -178,6 +178,185 @@ "html" ] }, + { + "name": "hoa/consistency", + "version": "1.17.05.02", + "version_normalized": "1.17.05.02", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Consistency.git", + "reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Consistency/zipball/fd7d0adc82410507f332516faf655b6ed22e4c2f", + "reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f", + "shasum": "" + }, + "require": { + "hoa/exception": "~1.0", + "php": ">=5.5.0" + }, + "require-dev": { + "hoa/stream": "~1.0", + "hoa/test": "~2.0" + }, + "time": "2017-05-02T12:18:12+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Hoa\\Consistency\\": "." + }, + "files": [ + "Prelude.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Consistency library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "autoloader", + "callable", + "consistency", + "entity", + "flex", + "keyword", + "library" + ] + }, + { + "name": "hoa/event", + "version": "1.17.01.13", + "version_normalized": "1.17.01.13", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Event.git", + "reference": "6c0060dced212ffa3af0e34bb46624f990b29c54" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Event/zipball/6c0060dced212ffa3af0e34bb46624f990b29c54", + "reference": "6c0060dced212ffa3af0e34bb46624f990b29c54", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "time": "2017-01-13T15:30:50+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Hoa\\Event\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Event library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "event", + "library", + "listener", + "observer" + ] + }, + { + "name": "hoa/exception", + "version": "1.17.01.16", + "version_normalized": "1.17.01.16", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Exception.git", + "reference": "091727d46420a3d7468ef0595651488bfc3a458f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Exception/zipball/091727d46420a3d7468ef0595651488bfc3a458f", + "reference": "091727d46420a3d7468ef0595651488bfc3a458f", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/event": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "time": "2017-01-16T07:53:27+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Hoa\\Exception\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Exception library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "exception", + "library" + ] + }, { "name": "masterminds/html5", "version": "2.6.0", diff --git a/vendor/hoa/consistency/.State b/vendor/hoa/consistency/.State new file mode 100644 index 0000000000..a604de473a --- /dev/null +++ b/vendor/hoa/consistency/.State @@ -0,0 +1 @@ +finalized diff --git a/vendor/hoa/consistency/.gitignore b/vendor/hoa/consistency/.gitignore new file mode 100644 index 0000000000..4fbb073c49 --- /dev/null +++ b/vendor/hoa/consistency/.gitignore @@ -0,0 +1,2 @@ +/vendor/ +/composer.lock diff --git a/vendor/hoa/consistency/.travis.yml b/vendor/hoa/consistency/.travis.yml new file mode 100644 index 0000000000..b44d94486c --- /dev/null +++ b/vendor/hoa/consistency/.travis.yml @@ -0,0 +1,57 @@ +language: php + +matrix: + include: + - php: 5.5 + - php: 5.6 + - php: 7.0 + - php: 7.1 + env: + - ENABLE_XDEBUG=true + - php: 7.1 + env: + - ENABLE_DEVTOOLS=true + - php: nightly + - php: hhvm-3.12 + sudo: required + dist: trusty + group: edge + - php: hhvm + sudo: required + dist: trusty + group: edge + allow_failures: + - php: nightly + - php: hhvm-3.12 + - php: hhvm + fast_finish: true + +os: + - linux + +notifications: + irc: "chat.freenode.net#hoaproject" + +sudo: false + +env: + global: + - secure: "AAAAB3NzaC1yc2EAAAADAQABAAACAQDIf0Rf76Hhkflz5b9UzWjOjk4UlMU5ySk0VY3B4WdHDLWMMK7fBp1Aj9qXWEDwkuX/NbQP1gB8jQNo7i5uZEOfu7Mn2svPkBBtnmKmaJhk90xypM4lcpcdPi4e8kXUgkriNQLQ2bRe1qZIeF115FkuIvActq7iWKY1TVSZbO54cDKMifDZfH09cf4vpwrZJqwZG6PUnUcCYijgDy99HtfRvzf9xalO4yWm55ZEbJ/VNTHlq1EhK73QLdHC7MO+OQFcd5wEyMbNxBj/bDn/udgb0HsrDijComTg/oTdQJMspYDQYV3ZYvpGozTTCVQrVTYYTP9RCNstgJLHDv9fZZW6yRlw4yNsT7jIQRLs/7awTxOAvRlxqaxk0//ECVNhDgawVtlbEIKrqnM1N7QTm0gjE0HkWEzxE0QbgoZqlLFD6qCp6WVvIT3uGY/i4TkVy78wf3/fzCKbrf72kYSbxIOCxVtptOmrgAblNEpiA/uZ9IofR2p2iwiVY1xF/mzxV2M4zCw6WASrlDhkaL0IncEdRtBuV2WTpixmtjmNkE9h/90kzb5cKExU786gZmvyflYvqlNlcMo3dNsDnROjQCAUXGBw5+risdqTT295BGmlEdZUtcf0c6/zEGhR8B7CktWYLSgOL5mpGMVNEBzyzEwnIiWCvI3pGgoV3Z9UzSJWKQ==" + +cache: + directories: + - vendor/ + +before_script: + - export PATH="$PATH:$HOME/.composer/vendor/bin" + - if [[ ! $ENABLE_XDEBUG ]]; then + phpenv config-rm xdebug.ini || echo "ext-xdebug is not available, cannot remove it."; + fi + +script: + - composer install + - vendor/bin/hoa test:run + - if [[ $ENABLE_DEVTOOLS ]]; then + composer global require friendsofphp/php-cs-fixer; + vendor/bin/hoa devtools:cs --diff --dry-run .; + fi diff --git a/vendor/hoa/consistency/Autoloader.php b/vendor/hoa/consistency/Autoloader.php new file mode 100644 index 0000000000..76f8e6c9b7 --- /dev/null +++ b/vendor/hoa/consistency/Autoloader.php @@ -0,0 +1,260 @@ +_namespacePrefixesToBaseDirectories[$prefix])) { + $this->_namespacePrefixesToBaseDirectories[$prefix] = []; + } + + if (true === $prepend) { + array_unshift( + $this->_namespacePrefixesToBaseDirectories[$prefix], + $baseDirectory + ); + } else { + array_push( + $this->_namespacePrefixesToBaseDirectories[$prefix], + $baseDirectory + ); + } + + return; + } + + /** + * Try to load the entity file for a given entity name. + * + * @param string $entity Entity name to load. + * @return bool + */ + public function load($entity) + { + $entityPrefix = $entity; + $hasBaseDirectory = false; + + while (false !== $pos = strrpos($entityPrefix, '\\')) { + $currentEntityPrefix = substr($entity, 0, $pos + 1); + $entityPrefix = rtrim($currentEntityPrefix, '\\'); + $entitySuffix = substr($entity, $pos + 1); + $entitySuffixAsPath = str_replace('\\', '/', $entitySuffix); + + if (false === $this->hasBaseDirectory($currentEntityPrefix)) { + continue; + } + + $hasBaseDirectory = true; + + foreach ($this->getBaseDirectories($currentEntityPrefix) as $baseDirectory) { + $file = $baseDirectory . $entitySuffixAsPath . '.php'; + + if (false !== $this->requireFile($file)) { + return $file; + } + } + } + + if (true === $hasBaseDirectory && + $entity === Consistency::getEntityShortestName($entity) && + false !== $pos = strrpos($entity, '\\')) { + return $this->runAutoloaderStack( + $entity . '\\' . substr($entity, $pos + 1) + ); + } + + return null; + } + + /** + * Require a file if exists. + * + * @param string $filename File name. + * @return bool + */ + public function requireFile($filename) + { + if (false === file_exists($filename)) { + return false; + } + + require $filename; + + return true; + } + + /** + * Check whether at least one base directory exists for a namespace prefix. + * + * @param string $namespacePrefix Namespace prefix. + * @return bool + */ + public function hasBaseDirectory($namespacePrefix) + { + return isset($this->_namespacePrefixesToBaseDirectories[$namespacePrefix]); + } + + /** + * Get declared base directories for a namespace prefix. + * + * @param string $namespacePrefix Namespace prefix. + * @return array + */ + public function getBaseDirectories($namespacePrefix) + { + if (false === $this->hasBaseDirectory($namespacePrefix)) { + return []; + } + + return $this->_namespacePrefixesToBaseDirectories[$namespacePrefix]; + } + + /** + * Get loaded classes. + * + * @return array + */ + public static function getLoadedClasses() + { + return get_declared_classes(); + } + + /** + * Run the entire autoloader stack with a specific entity. + * + * @param string $entity Entity name to load. + * @return void + */ + public function runAutoloaderStack($entity) + { + return spl_autoload_call($entity); + } + + /** + * Register the autoloader. + * + * @param bool $prepend Prepend this autoloader to the stack or not. + * @return bool + */ + public function register($prepend = false) + { + return spl_autoload_register([$this, 'load'], true, $prepend); + } + + /** + * Unregister the autoloader. + * + * @return bool + */ + public function unregister() + { + return spl_autoload_unregister([$this, 'load']); + } + + /** + * Get all registered autoloaders (not only from this library). + * + * @return array + */ + public function getRegisteredAutoloaders() + { + return spl_autoload_functions(); + } + + /** + * Dynamic new, a simple factory. + * It loads and constructs a class, with provided arguments. + * + * @param bool $classname Classname. + * @param array $arguments Arguments for the constructor. + * @return object + */ + public static function dnew($classname, array $arguments = []) + { + $classname = ltrim($classname, '\\'); + + if (false === Consistency::entityExists($classname, false)) { + spl_autoload_call($classname); + } + + $class = new \ReflectionClass($classname); + + if (empty($arguments) || false === $class->hasMethod('__construct')) { + return $class->newInstance(); + } + + return $class->newInstanceArgs($arguments); + } +} + +/** + * Autoloader. + */ +$autoloader = new Autoloader(); +$autoloader->addNamespace('Hoa', dirname(__DIR__)); +$autoloader->register(); diff --git a/vendor/hoa/consistency/CHANGELOG.md b/vendor/hoa/consistency/CHANGELOG.md new file mode 100644 index 0000000000..21067ad663 --- /dev/null +++ b/vendor/hoa/consistency/CHANGELOG.md @@ -0,0 +1,51 @@ +# 1.17.05.02 + + * CI: Set up Travis. (Ivan Enderlin, 2017-03-08T09:52:17+01:00) + * Prelude: Remove the `(unset)` cast. (Ivan Enderlin, 2017-03-07T16:55:13+01:00) + +# 1.17.01.10 + + * Quality: Happy new year! (Alexis von Glasow, 2017-01-09T21:38:10+01:00) + * Documentation: New `README.md` file. (Ivan Enderlin, 2016-10-19T16:27:31+02:00) + * Documentation: Fix `docs` and `source` links. (Ivan Enderlin, 2016-10-05T20:26:20+02:00) + * Documentation: Update `support` properties. (Ivan Enderlin, 2016-10-05T15:56:01+02:00) + * Consistency: `void` is a reserved keyword now. (Ivan Enderlin, 2016-09-02T11:06:18+02:00) + * Consistency: Remove `trait_exists` polyfill. (Ivan Enderlin, 2016-08-23T17:26:07+02:00) + +# 1.16.03.03 + + * Add `STREAM_CRYPTO_METHOD_*` constants on PHP 5.5. (Metalaka, 2016-02-29T21:10:14+01:00) + * Composer: Fix `hoa/stream` dependency. (Ivan Enderlin, 2016-03-03T10:13:50+01:00) + +# 1.16.01.14 + + * Test: Write cases for flex entity in autoloader. (Ivan Enderlin, 2016-01-14T10:45:08+01:00) + * Autoloader: Restrict loads to mapped entities. (Ivan Enderlin, 2016-01-14T10:38:21+01:00) + +# 1.16.01.11 + + * Quality: Drop PHP5.4. (Ivan Enderlin, 2016-01-11T09:15:26+01:00) + * Quality: Run devtools:cs. (Ivan Enderlin, 2016-01-09T08:58:31+01:00) + * Core: Remove `Hoa\Core`. (Ivan Enderlin, 2016-01-09T08:03:33+01:00) + +# 0.16.01.06 + + * Prelude: Introduce the prelude/preamble! (Ivan Enderlin, 2015-12-09T08:34:16+01:00) + * Consistency: Import last methods from `Hoa\Core`. (Ivan Enderlin, 2015-12-09T08:24:02+01:00) + * Quality: Fix CS. (Ivan Enderlin, 2015-12-09T06:43:22+01:00) + * Add a `.gitignore` file. (Metalaka, 2015-12-03T13:21:11+01:00) + * Autoloader: Propagate unknown entity on the stack. (Ivan Enderlin, 2015-12-03T11:04:57+01:00) + * Autoloader: Auto-register to support flex entity. (Ivan Enderlin, 2015-12-03T10:01:23+01:00) + * Composer: Force some files to load. (Ivan Enderlin, 2015-12-03T08:15:55+01:00) + * Test: Simplify `case_register`. (Ivan Enderlin, 2015-12-03T08:15:19+01:00) + * Consistency: Use a strict equality check on trait. (Ivan Enderlin, 2015-12-02T17:11:50+01:00) + * README: First draft. (Ivan Enderlin, 2015-12-02T08:40:34+01:00) + * Documentation: Update API documentation. (Ivan Enderlin, 2015-12-02T08:37:58+01:00) + * Autoloader: Support flex entities. (Ivan Enderlin, 2015-12-02T08:18:39+01:00) + * Test: Write test suite of `…nsistency\Autoloader`. (Ivan Enderlin, 2015-12-01T08:42:30+01:00) + * Test: Write test suite of `…sistency\Consistency`. (Ivan Enderlin, 2015-11-25T22:10:30+01:00) + * Test: Write test suite of `…onsistency\Xcallable`. (Ivan Enderlin, 2015-11-25T08:45:59+01:00) + * Test: Write test suite of `…onsistency\Exception`. (Ivan Enderlin, 2015-11-24T16:59:18+01:00) + * Split from `Hoa\Core`. (Ivan Enderlin, 2015-11-23T23:08:19+01:00) + +(first snapshot) diff --git a/vendor/hoa/consistency/Consistency.php b/vendor/hoa/consistency/Consistency.php new file mode 100644 index 0000000000..d1da5a6d5d --- /dev/null +++ b/vendor/hoa/consistency/Consistency.php @@ -0,0 +1,363 @@ += $count) { + return $entityName; + } + + if ($parts[$count - 2] === $parts[$count - 1]) { + return implode('\\', array_slice($parts, 0, -1)); + } + + return $entityName; + } + + /** + * Declare a flex entity (for nested library). + * + * @param string $entityName Entity name. + * @return bool + */ + public static function flexEntity($entityName) + { + return class_alias( + $entityName, + static::getEntityShortestName($entityName), + false + ); + } + + /** + * Whether a word is reserved or not. + * + * @param string $word Word. + * @return bool + */ + public static function isKeyword($word) + { + static $_list = [ + // PHP keywords. + '__halt_compiler', + 'abstract', + 'and', + 'array', + 'as', + 'bool', + 'break', + 'callable', + 'case', + 'catch', + 'class', + 'clone', + 'const', + 'continue', + 'declare', + 'default', + 'die', + 'do', + 'echo', + 'else', + 'elseif', + 'empty', + 'enddeclare', + 'endfor', + 'endforeach', + 'endif', + 'endswitch', + 'endwhile', + 'eval', + 'exit', + 'extends', + 'false', + 'final', + 'float', + 'for', + 'foreach', + 'function', + 'global', + 'goto', + 'if', + 'implements', + 'include', + 'include_once', + 'instanceof', + 'insteadof', + 'int', + 'interface', + 'isset', + 'list', + 'mixed', + 'namespace', + 'new', + 'null', + 'numeric', + 'object', + 'or', + 'print', + 'private', + 'protected', + 'public', + 'require', + 'require_once', + 'resource', + 'return', + 'static', + 'string', + 'switch', + 'throw', + 'trait', + 'true', + 'try', + 'unset', + 'use', + 'var', + 'void', + 'while', + 'xor', + 'yield', + + // Compile-time constants. + '__class__', + '__dir__', + '__file__', + '__function__', + '__line__', + '__method__', + '__namespace__', + '__trait__' + ]; + + return in_array(strtolower($word), $_list); + } + + /** + * Whether an ID is a valid PHP identifier. + * + * @param string $id ID. + * @return bool + */ + public static function isIdentifier($id) + { + return 0 !== preg_match( + '#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x80-\xff]*$#', + $id + ); + } + + /** + * Register a register shutdown function. + * It may be analogous to a super static destructor. + * + * @param callable $callable Callable. + * @return bool + */ + public static function registerShutdownFunction($callable) + { + return register_shutdown_function($callable); + } + + /** + * Get PHP executable. + * + * @return string + */ + public static function getPHPBinary() + { + if (defined('PHP_BINARY')) { + return PHP_BINARY; + } + + if (isset($_SERVER['_'])) { + return $_SERVER['_']; + } + + foreach (['', '.exe'] as $extension) { + if (file_exists($_ = PHP_BINDIR . DS . 'php' . $extension)) { + return realpath($_); + } + } + + return null; + } + + /** + * Generate an Universal Unique Identifier (UUID). + * + * @return string + */ + public static function uuid() + { + return sprintf( + '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', + mt_rand(0, 0xffff), + mt_rand(0, 0xffff), + mt_rand(0, 0xffff), + mt_rand(0, 0x0fff) | 0x4000, + mt_rand(0, 0x3fff) | 0x8000, + mt_rand(0, 0xffff), + mt_rand(0, 0xffff), + mt_rand(0, 0xffff) + ); + } +} + +} + +namespace +{ + +if (70000 > PHP_VERSION_ID && false === interface_exists('Throwable', false)) { + /** + * Implement a fake Throwable class, introduced in PHP7.0. + */ + interface Throwable + { + public function getMessage(); + public function getCode(); + public function getFile(); + public function getLine(); + public function getTrace(); + public function getPrevious(); + public function getTraceAsString(); + public function __toString(); + } +} + +/** + * Define TLSv* constants, introduced in PHP 5.5. + */ +if (50600 > PHP_VERSION_ID) { + $define = function ($constantName, $constantValue, $case = false) { + if (!defined($constantName)) { + return define($constantName, $constantValue, $case); + } + + return false; + }; + + $define('STREAM_CRYPTO_METHOD_TLSv1_0_SERVER', 8); + $define('STREAM_CRYPTO_METHOD_TLSv1_1_SERVER', 16); + $define('STREAM_CRYPTO_METHOD_TLSv1_2_SERVER', 32); + $define('STREAM_CRYPTO_METHOD_ANY_SERVER', 62); + + $define('STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT', 9); + $define('STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT', 17); + $define('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT', 33); + $define('STREAM_CRYPTO_METHOD_ANY_CLIENT', 63); +} + +if (!function_exists('curry')) { + /** + * Curry. + * Example: + * $c = curry('str_replace', …, …, 'foobar'); + * var_dump($c('foo', 'baz')); // bazbar + * $c = curry('str_replace', 'foo', 'baz', …); + * var_dump($c('foobarbaz')); // bazbarbaz + * Nested curries also work: + * $c1 = curry('str_replace', …, …, 'foobar'); + * $c2 = curry($c1, 'foo', …); + * var_dump($c2('baz')); // bazbar + * Obviously, as the first argument is a callable, we can combine this with + * \Hoa\Consistency\Xcallable ;-). + * The “…” character is the HORIZONTAL ELLIPSIS Unicode character (Unicode: + * 2026, UTF-8: E2 80 A6). + * + * @param mixed $callable Callable (two parts). + * @param ... ... Arguments. + * @return \Closure + */ + function curry($callable) + { + $arguments = func_get_args(); + array_shift($arguments); + $ii = array_keys($arguments, …, true); + + return function () use ($callable, $arguments, $ii) { + return call_user_func_array( + $callable, + array_replace($arguments, array_combine($ii, func_get_args())) + ); + }; + } +} + +/** + * Flex entity. + */ +Hoa\Consistency\Consistency::flexEntity('Hoa\Consistency\Consistency'); + +} diff --git a/vendor/hoa/consistency/Exception.php b/vendor/hoa/consistency/Exception.php new file mode 100644 index 0000000000..c7ae2a3a1c --- /dev/null +++ b/vendor/hoa/consistency/Exception.php @@ -0,0 +1,51 @@ + + Hoa +

+ +--- + +

+ Build status + Code coverage + Packagist + License +

+

+ Hoa is a modular, extensible and + structured set of PHP libraries.
+ Moreover, Hoa aims at being a bridge between industrial and research worlds. +

+ +# Hoa\Consistency + +[![Help on IRC](https://img.shields.io/badge/help-%23hoaproject-ff0066.svg)](https://webchat.freenode.net/?channels=#hoaproject) +[![Help on Gitter](https://img.shields.io/badge/help-gitter-ff0066.svg)](https://gitter.im/hoaproject/central) +[![Documentation](https://img.shields.io/badge/documentation-hack_book-ff0066.svg)](https://central.hoa-project.net/Documentation/Library/Consistency) +[![Board](https://img.shields.io/badge/organisation-board-ff0066.svg)](https://waffle.io/hoaproject/consistency) + +This library provides a thin layer between PHP VMs and libraries to ensure +consistency accross VM versions and library versions. + +[Learn more](https://central.hoa-project.net/Documentation/Library/Consistency). + +## Installation + +With [Composer](https://getcomposer.org/), to include this library into +your dependencies, you need to +require [`hoa/consistency`](https://packagist.org/packages/hoa/consistency): + +```sh +$ composer require hoa/consistency '~1.0' +``` + +For more installation procedures, please read [the Source +page](https://hoa-project.net/Source.html). + +## Testing + +Before running the test suites, the development dependencies must be installed: + +```sh +$ composer install +``` + +Then, to run all the test suites: + +```sh +$ vendor/bin/hoa test:run +``` + +For more information, please read the [contributor +guide](https://hoa-project.net/Literature/Contributor/Guide.html). + +## Quick usage + +We propose a quick overview of how the consistency API ensures foreward and +backward compatibility, also an overview of the [PSR-4 +autoloader](http://www.php-fig.org/psr/psr-4/) and the xcallable API. + +### Foreward and backward compatibility + +The `Hoa\Consistency\Consistency` class ensures foreward and backward +compatibility. + +#### Example with keywords + +The `Hoa\Consistency\Consistency::isKeyword` checks whether a specific word is +reserved by PHP or not. Let's say your current PHP version does not support the +`callable` keyword or type declarations such as `int`, `float`, `string` etc., +the `isKeyword` method will tell you if they are reserved keywords: Not only +for your current PHP version, but maybe in an incoming version. + +```php +$isKeyword = Hoa\Consistency\Consistency::isKeyword('yield'); +``` + +It avoids to write algorithms that might break in the future or for your users +living on the edge. + +#### Example with identifiers + +PHP identifiers are defined by a regular expression. It might change in the +future. To prevent breaking your algorithms, you can use the +`Hoa\Consistency\Consistency::isIdentifier` method to check an identifier is +correct regarding current PHP version: + +```php +$isValidIdentifier = Hoa\Consistency\Consistency::isIdentifier('foo'); +``` + +#### Flexible entities + +Flexible entities are very simple. If we declare `Foo\Bar\Bar` as a flexible +entity, we will be able to access it with the `Foo\Bar\Bar` name or `Foo\Bar`. +This is very useful if your architecture evolves but you want to keep the +backward compatibility. For instance, it often happens that you create a +`Foo\Bar\Exception` class in the `Foo/Bar/Exception.php` file. But after few +versions, you realise other exceptions need to be introduced, so you need an +`Exception` directory. In this case, `Foo\Bar\Exception` should move as +`Foo\Bar\Exception\Exception`. If this latter is declared as a flexible entity, +backward compatibility will be kept. + +```php +Hoa\Consistency\Consistency::flexEntity('Foo\Bar\Exception\Exception'); +``` + +Another example is the “entry-class” (informal naming). +`Hoa\Consistency\Consistency` is a good example. This is more convenient to +write `Hoa\Consistency` instead of `Hoa\Consistency\Consistency`. This is +possible because this is a flexible entity. + +#### Throwable & co. + +The `Throwable` interface has been introduced to represent a whole new exception +architecture in PHP. Thus, to be compatible with incoming PHP versions, you +might want to use this interface in some cases. Hopefully, the `Throwable` +interface will be created for you if it does not exists. + +```php +try { + … +} catch (Throwable $e) { + … +} +``` + +### Autoloader + +`Hoa\Consistency\Autoloader` is a [PSR-4 +compatible](http://www.php-fig.org/psr/psr-4/) autoloader. It simply works as +follows: + * `addNamespace` is used to map a namespace prefix to a directory, + * `register` is used to register the autoloader. + +The API also provides the `load` method to force the load of an entity, +`unregister` to unregister the autoloader, `getRegisteredAutoloaders` to get +a list of all registered autoloaders etc. + +For instance, to map the `Foo\Bar` namespace to the `Source/` directory: + +```php +$autoloader = new Hoa\Consistency\Autoloader(); +$autoloader->addNamespace('Foo\Bar', 'Source'); +$autoloader->register(); + +$baz = new Foo\Bar\Baz(); // automatically loaded! +``` + +### Xcallable + +Xcallables are “extended callables”. It is a unified API to invoke callables of +any kinds, and also extends some Hoa's API (like +[`Hoa\Event`](https://central.hoa-project.net/Resource/Library/Event) +or +[`Hoa\Stream`](https://central.hoa-project.net/Resource/Library/Stream)). It +understands the following kinds: + * `'function'` as a string, + * `'class::method'` as a string, + * `'class', 'method'` as 2 string arguments, + * `$object, 'method'` as 2 arguments, + * `$object, ''` as 2 arguments, the “able” is unknown, + * `function (…) { … }` as a closure, + * `['class', 'method']` as an array of strings, + * `[$object, 'method']` as an array. + +To use it, simply instanciate the `Hoa\Consistency\Xcallable` class and use it +as a function: + +```php +$xcallable = new Hoa\Consistency\Xcallable('strtoupper'); +var_dump($xcallable('foo')); + +/** + * Will output: + * string(3) "FOO" + */ +``` + +The `Hoa\Consistency\Xcallable::distributeArguments` method invokes the callable +but the arguments are passed as an array: + +```php +$xcallable->distributeArguments(['foo']); +``` + +This is also possible to get a unique hash of the callable: + +```php +var_dump($xcallable->getHash()); + +/** + * Will output: + * string(19) "function#strtoupper" + */ +``` + +Finally, this is possible to get a reflection instance of the current callable +(can be of kind [`ReflectionFunction`](http://php.net/ReflectionFunction), +[`ReflectionClass`](http://php.net/ReflectionClass), +[`ReflectionMethod`](http://php.net/ReflectionMethod) or +[`ReflectionObject`](http://php.net/ReflectionObject)): + +```php +var_dump($xcallable->getReflection()); + +/** + * Will output: + * object(ReflectionFunction)#42 (1) { + * ["name"]=> + * string(10) "strtoupper" + * } + */ +``` + +When the object is set but not the method, the latter will be deduced if +possible. If the object is of kind +[`Hoa\Stream`](http://central.hoa-project.net/Resource/Library/Stream), then +according to the type of the arguments given to the callable, the +`writeInteger`, `writeString`, `writeArray` etc. method will be used. If the +argument is of kind `Hoa\Event\Bucket`, then the method name will be deduced +based on the data contained inside the event bucket. This is very handy. For +instance, the following example will work seamlessly: + +```php +Hoa\Event\Event::getEvent('hoa://Event/Exception') + ->attach(new Hoa\File\Write('Exceptions.log')); +``` + +The `attach` method on `Hoa\Event\Event` transforms its argument as an +xcallable. In this particular case, the method to call is unknown, we only have +an object (of kind `Hoa\File\Write`). However, because this is a stream, the +method will be deduced according to the data contained in the event bucket fired +on the `hoa://Event/Exception` event channel. + +## Documentation + +The +[hack book of `Hoa\Consistency`](https://central.hoa-project.net/Documentation/Library/Consistency) +contains detailed information about how to use this library and how it works. + +To generate the documentation locally, execute the following commands: + +```sh +$ composer require --dev hoa/devtools +$ vendor/bin/hoa devtools:documentation --open +``` + +More documentation can be found on the project's website: +[hoa-project.net](https://hoa-project.net/). + +## Getting help + +There are mainly two ways to get help: + + * On the [`#hoaproject`](https://webchat.freenode.net/?channels=#hoaproject) + IRC channel, + * On the forum at [users.hoa-project.net](https://users.hoa-project.net). + +## Contribution + +Do you want to contribute? Thanks! A detailed [contributor +guide](https://hoa-project.net/Literature/Contributor/Guide.html) explains +everything you need to know. + +## License + +Hoa is under the New BSD License (BSD-3-Clause). Please, see +[`LICENSE`](https://hoa-project.net/LICENSE) for details. diff --git a/vendor/hoa/consistency/Test/Unit/Autoloader.php b/vendor/hoa/consistency/Test/Unit/Autoloader.php new file mode 100644 index 0000000000..002983f72d --- /dev/null +++ b/vendor/hoa/consistency/Test/Unit/Autoloader.php @@ -0,0 +1,342 @@ +given( + $autoloader = new SUT(), + $prefix = 'Foo\Bar\\', + $baseDirectoryA = 'Source/Foo/Bar/', + $baseDirectoryB = 'Source/Foo/Bar/' + ) + ->when( + $autoloader->addNamespace($prefix, $baseDirectoryA), + $result = $autoloader->addNamespace($prefix, $baseDirectoryB) + ) + ->then + ->boolean($autoloader->hasBaseDirectory($prefix)) + ->isTrue() + ->array($autoloader->getBaseDirectories($prefix)) + ->isEqualTo([ + $baseDirectoryB, + $baseDirectoryA + ]); + } + + public function case_add_namespace_append() + { + $this + ->given( + $autoloader = new SUT(), + $prefix = 'Foo\Bar\\', + $baseDirectoryA = 'Source/Foo/Bar/', + $baseDirectoryB = 'Source/Foo/Bar/' + ) + ->when( + $autoloader->addNamespace($prefix, $baseDirectoryA), + $result = $autoloader->addNamespace($prefix, $baseDirectoryB) + ) + ->then + ->boolean($autoloader->hasBaseDirectory($prefix)) + ->isTrue() + ->array($autoloader->getBaseDirectories($prefix)) + ->isEqualTo([ + $baseDirectoryA, + $baseDirectoryB + ]); + } + + public function case_add_namespace_with_invalid_prefix() + { + $this + ->given( + $autoloader = new SUT(), + $prefix = '\\\\Foo\Bar', + $baseDirectory = 'Source/Foo/Bar/' + ) + ->when($result = $autoloader->addNamespace($prefix, $baseDirectory)) + ->then + ->boolean($autoloader->hasBaseDirectory('Foo\Bar\\')) + ->isTrue() + ->array($autoloader->getBaseDirectories('Foo\Bar\\')) + ->isEqualTo([$baseDirectory]); + } + + public function case_add_namespace_with_invalid_base_directory() + { + $this + ->given( + $autoloader = new SUT(), + $prefix = 'Foo\Bar\\', + $baseDirectory = 'Source/Foo/Bar' + ) + ->when($result = $autoloader->addNamespace($prefix, $baseDirectory)) + ->then + ->boolean($autoloader->hasBaseDirectory('Foo\Bar\\')) + ->isTrue() + ->array($autoloader->getBaseDirectories('Foo\Bar\\')) + ->isEqualTo(['Source/Foo/Bar/']); + } + + public function case_add_namespace_with_crazy_invalid_base_directory() + { + $this + ->given( + $autoloader = new SUT(), + $prefix = 'Foo\Bar\\', + $baseDirectory = 'Source/Foo/Bar/////' + ) + ->when($result = $autoloader->addNamespace($prefix, $baseDirectory)) + ->then + ->boolean($autoloader->hasBaseDirectory('Foo\Bar\\')) + ->isTrue() + ->array($autoloader->getBaseDirectories('Foo\Bar\\')) + ->isEqualTo(['Source/Foo/Bar/']); + } + + public function case_load() + { + $this + ->given( + $autoloader = new \Mock\Hoa\Consistency\Autoloader(), + $autoloader->addNamespace('Foo\Bar\\', 'Source/Foo/Bar/'), + $this->calling($autoloader)->requireFile = function ($file) { + return $file; + } + ) + ->when($result = $autoloader->load('Foo\Bar\Baz\Qux')) + ->then + ->string($result) + ->isEqualTo('Source/Foo/Bar/Baz/Qux.php'); + } + + public function case_load_invalid_entity() + { + $this + ->given($autoloader = new SUT()) + ->when($result = $autoloader->load('Foo')) + ->then + ->variable($result) + ->isNull(); + } + + public function case_load_flex_entity() + { + $self = $this; + + $this + ->given( + $autoloader = new \Mock\Hoa\Consistency\Autoloader(), + $autoloader->addNamespace('Foo\Bar\\', 'Source/Foo/'), + $this->calling($autoloader)->runAutoloaderStack = function ($entity) use ($self, &$called) { + $called = true; + $self + ->string($entity) + ->isEqualTo('Foo\Bar\Baz\Baz'); + + return; + }, + $autoloader->register() + ) + ->when($result = $autoloader->load('Foo\Bar\Baz')) + ->then + ->variable($result) + ->isNull() + ->boolean($called) + ->isTrue(); + } + + public function case_load_unmapped_flex_entity() + { + $self = $this; + + $this + ->given( + $autoloader = new \Mock\Hoa\Consistency\Autoloader(), + $this->calling($autoloader)->runAutoloaderStack = function ($entity) use ($self, &$called) { + $called = true; + + return; + }, + $autoloader->register() + ) + ->when($result = $autoloader->load('Foo\Bar\Baz')) + ->then + ->variable($result) + ->isNull() + ->variable($called) + ->isNull(); + } + + public function case_require_existing_file() + { + $this + ->given( + $autoloader = new SUT(), + + $this->function->file_exists = true, + + $constantName = 'HOA_TEST_' . uniqid(), + $filename = 'hoa://Test/Vfs/Foo?type=file', + + file_put_contents($filename, 'when($result = $autoloader->requireFile($filename)) + ->then + ->boolean($result) + ->isTrue() + ->string(constant($constantName)) + ->isEqualTo('BAR'); + } + + public function case_require_not_existing_file() + { + $this + ->given( + $autoloader = new SUT(), + $this->function->file_exists = false + ) + ->when($result = $autoloader->requireFile('/hoa/flatland')) + ->then + ->boolean($result) + ->isFalse(); + } + + public function case_has_not_base_directory() + { + $this + ->given($autoloader = new SUT()) + ->when($result = $autoloader->hasBaseDirectory('foo')) + ->then + ->boolean($result) + ->isFalse(); + } + + public function case_get_base_undeclared_namespace_prefix() + { + $this + ->given($autoloader = new SUT()) + ->when($result = $autoloader->getBaseDirectories('foo')) + ->then + ->array($result) + ->isEmpty(); + } + + public function case_dnew() + { + $this + ->given($classname = 'Hoa\Consistency\Autoloader') + ->when($result = SUT::dnew($classname)) + ->then + ->object($result) + ->isInstanceOf($classname); + } + + public function case_dnew_unknown_class() + { + $this + ->given($this->function->spl_autoload_call = null) + ->exception(function () { + SUT::dnew('Foo'); + }) + ->isInstanceOf('ReflectionException'); + } + + public function case_get_loaded_classes() + { + $this + ->given( + $declaredClasses = get_declared_classes(), + $this->function->get_declared_classes = $declaredClasses + ) + ->when($result = SUT::getLoadedClasses()) + ->then + ->array($result) + ->isEqualTo($declaredClasses); + } + + public function case_register() + { + $self = $this; + + $this + ->given($autoloader = new SUT()) + ->when($result = $autoloader->register()) + ->then + ->boolean($result) + ->isTrue() + ->array($autoloader->getRegisteredAutoloaders()) + ->isEqualTo(spl_autoload_functions()); + } + + public function case_unregister() + { + $this + ->given( + $autoloader = new SUT(), + $oldRegisteredAutoloaders = $autoloader->getRegisteredAutoloaders() + ) + ->when($result = $autoloader->register()) + ->then + ->boolean($result) + ->isTrue() + ->integer(count($autoloader->getRegisteredAutoloaders())) + ->isEqualTo(count($oldRegisteredAutoloaders) + 1) + + ->when($result = $autoloader->unregister()) + ->then + ->boolean($result) + ->isTrue() + ->array($autoloader->getRegisteredAutoloaders()) + ->isEqualTo($oldRegisteredAutoloaders); + } +} diff --git a/vendor/hoa/consistency/Test/Unit/Consistency.php b/vendor/hoa/consistency/Test/Unit/Consistency.php new file mode 100644 index 0000000000..f923fc795e --- /dev/null +++ b/vendor/hoa/consistency/Test/Unit/Consistency.php @@ -0,0 +1,325 @@ +given( + $this->function->class_exists = $class, + $this->function->interface_exists = $interface, + $this->function->trait_exists = $trait + ) + ->when($result = SUT::entityExists('foo')) + ->then + ->boolean($result) + ->isTrue(); + } + + public function case_entity_exists_with_class() + { + return $this->_entity_exists_with_xxx(true, false, false); + } + + public function case_entity_exists_with_interface() + { + return $this->_entity_exists_with_xxx(false, true, false); + } + + public function case_entity_exists_with_trait() + { + return $this->_entity_exists_with_xxx(false, false, true); + } + + public function case_entity_does_not_exists() + { + $this + ->given( + $this->function->class_exists = false, + $this->function->interface_exists = false, + $this->function->trait_exists = false + ) + ->when($result = SUT::entityExists('foo')) + ->then + ->boolean($result) + ->isFalse(); + } + + public function case_get_entity_shortest_name() + { + $this + ->when($result = SUT::getEntityShortestName('Foo\Bar\Bar')) + ->then + ->string($result) + ->isEqualTo('Foo\Bar'); + } + + public function case_get_entity_shortest_name_with_already_the_shortest() + { + $this + ->when($result = SUT::getEntityShortestName('Foo\Bar')) + ->then + ->string($result) + ->isEqualTo('Foo\Bar'); + } + + public function case_get_entity_shortest_name_with_no_namespace() + { + $this + ->when($result = SUT::getEntityShortestName('Foo')) + ->then + ->string($result) + ->isEqualTo('Foo'); + } + + public function case_is_keyword() + { + $this + ->given( + $keywords = [ + '__HALT_COMPILER', + 'abstract', + 'and', + 'array', + 'as', + 'bool', + 'break', + 'callable', + 'case', + 'catch', + 'class', + 'clone', + 'const', + 'continue', + 'declare', + 'default', + 'die', + 'do', + 'echo', + 'else', + 'elseif', + 'empty', + 'enddeclare', + 'endfor', + 'endforeach', + 'endif', + 'endswitch', + 'endwhile', + 'eval', + 'exit', + 'extends', + 'false', + 'final', + 'float', + 'for', + 'foreach', + 'function', + 'global', + 'goto', + 'if', + 'implements', + 'include', + 'include_once', + 'instanceof', + 'insteadof', + 'int', + 'interface', + 'isset', + 'list', + 'mixed', + 'namespace', + 'new', + 'null', + 'numeric', + 'object', + 'or', + 'print', + 'private', + 'protected', + 'public', + 'require', + 'require_once', + 'resource', + 'return', + 'static', + 'string', + 'switch', + 'throw', + 'trait', + 'true', + 'try', + 'unset', + 'use', + 'var', + 'void', + 'while', + 'xor', + 'yield', + '__CLASS__', + '__DIR__', + '__FILE__', + '__FUNCTION__', + '__LINE__', + '__METHOD__', + '__NAMESPACE__', + '__TRAIT__' + ] + ) + ->when(function () use ($keywords) { + foreach ($keywords as $keyword) { + $this + ->boolean(SUT::isKeyword($keyword)) + ->isTrue(); + } + }); + } + + public function case_is_identifier() + { + $this + ->given($_identifier = $this->realdom->regex('#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x80-\xff]*$#')) + ->when(function () use ($_identifier) { + foreach ($this->sampleMany($_identifier, 1000) as $identifier) { + $this + ->boolean(SUT::isIdentifier($identifier)) + ->isTrue(); + } + }); + } + + public function case_register_shutdown_function() + { + $self = $this; + + $this + ->given( + $callable = function () { + }, + $this->function->register_shutdown_function = function ($_callable) use (&$called, $self, &$callable) { + $called = true; + + $self + ->variable($_callable) + ->isEqualTo($callable); + + return true; + } + ) + ->when($result = SUT::registerShutdownFunction($callable)) + ->then + ->boolean($result) + ->isTrue(); + } + + public function case_get_php_binary_with_constant() + { + $this + ->given($this->constant->PHP_BINARY = '/foo/php') + ->when($result = SUT::getPHPBinary()) + ->then + ->string($result) + ->isEqualTo('/foo/php'); + } + + public function case_get_php_binary_with_server() + { + $this + ->given( + $this->function->defined = false, + $_SERVER['_'] = '/bar/php' + ) + ->when($result = SUT::getPHPBinary()) + ->then + ->string($result) + ->isEqualTo('/bar/php'); + } + + public function case_get_php_binary_with_bin_directory() + { + unset($_SERVER['_']); + + $this + ->given( + $this->function->defined = false, + $this->function->file_exists = true, + $this->function->realpath = '/baz/php' + ) + ->when($result = SUT::getPHPBinary()) + ->then + ->string($result) + ->isEqualTo('/baz/php'); + } + + public function case_uuid() + { + $this + ->given($this->function->mt_rand = 42) + ->when($result = SUT::uuid()) + ->then + ->string($result) + ->isEqualTo('002a002a-002a-402a-802a-002a002a002a'); + } + + public function case_uuid_all_differents() + { + $this + ->when(function () { + $uuids = []; + + for ($i = 0; $i < 10000; ++$i) { + $uuids[] = SUT::uuid(); + } + + $this + ->integer(count($uuids)) + ->isEqualTo(count(array_unique($uuids))); + }); + } +} diff --git a/vendor/hoa/consistency/Test/Unit/Exception.php b/vendor/hoa/consistency/Test/Unit/Exception.php new file mode 100644 index 0000000000..7ea3f9658a --- /dev/null +++ b/vendor/hoa/consistency/Test/Unit/Exception.php @@ -0,0 +1,60 @@ +when($result = new SUT('foo', 0)) + ->then + ->object($result) + ->isInstanceOf('Hoa\Exception\Exception'); + } +} diff --git a/vendor/hoa/consistency/Test/Unit/Xcallable.php b/vendor/hoa/consistency/Test/Unit/Xcallable.php new file mode 100644 index 0000000000..61e9ed57f8 --- /dev/null +++ b/vendor/hoa/consistency/Test/Unit/Xcallable.php @@ -0,0 +1,341 @@ +when($result = new SUT('strtoupper')) + ->then + ->string($result('foo')) + ->isEqualTo('FOO') + ->string($result->getValidCallback()) + ->isEqualTo('strtoupper') + ->string($result->getHash()) + ->isEqualTo('function#strtoupper') + ->isEqualTo($result . '') + ->object($reflection = $result->getReflection()) + ->isInstanceOf('ReflectionFunction') + ->string($reflection->getName()) + ->isEqualTo('strtoupper'); + } + + public function case_form_class___method() + { + $this + ->when($result = new SUT(__CLASS__ . '::strtoupper')) + ->then + ->string($result('foo')) + ->isEqualTo('FOO') + ->array($result->getValidCallback()) + ->isEqualTo([__CLASS__, 'strtoupper']) + ->string($result->getHash()) + ->isEqualTo('class#' . __CLASS__ . '::strtoupper') + ->isEqualTo($result . '') + ->object($reflection = $result->getReflection()) + ->isInstanceOf('ReflectionMethod') + ->string($reflection->getName()) + ->isEqualTo('strtoupper'); + } + + public function case_form_class_method() + { + $this + ->when($result = new SUT(__CLASS__, 'strtoupper')) + ->then + ->string($result('foo')) + ->isEqualTo('FOO') + ->array($result->getValidCallback()) + ->isEqualTo([__CLASS__, 'strtoupper']) + ->string($result->getHash()) + ->isEqualTo('class#' . __CLASS__ . '::strtoupper') + ->isEqualTo($result . '') + ->object($reflection = $result->getReflection()) + ->isInstanceOf('ReflectionMethod') + ->string($reflection->getName()) + ->isEqualTo('strtoupper'); + } + + public function case_form_object_method() + { + $this + ->when($result = new SUT($this, 'strtolower')) + ->then + ->string($result('FOO')) + ->isEqualTo('foo') + ->array($result->getValidCallback()) + ->isEqualTo([$this, 'strtolower']) + ->string($result->getHash()) + ->matches( + '/^object\([^:]+\)#' . + preg_quote(__CLASS__) . + '::strtolower$/' + ) + ->isEqualTo($result . '') + ->object($reflection = $result->getReflection()) + ->isInstanceOf('ReflectionMethod') + ->string($reflection->getName()) + ->isEqualTo('strtolower'); + } + + public function case_form_object_invoke() + { + $this + ->when($result = new SUT($this)) + ->then + ->string($result('foo')) + ->isEqualTo('FOO') + ->array($result->getValidCallback()) + ->isEqualTo([$this, '__invoke']) + ->string($result->getHash()) + ->matches( + '/^object\([^:]+\)#' . + preg_quote(__CLASS__) . + '::__invoke$/' + ) + ->isEqualTo($result . '') + ->object($reflection = $result->getReflection()) + ->isInstanceOf('ReflectionMethod') + ->string($reflection->getName()) + ->isEqualTo('__invoke'); + } + + public function case_form_closure() + { + $this + ->given( + $closure = function ($string) { + return strtoupper($string); + } + ) + ->when($result = new SUT($closure)) + ->then + ->string($result('foo')) + ->isEqualTo('FOO') + ->object($result->getValidCallback()) + ->isIdenticalTo($closure) + ->string($result->getHash()) + ->matches('/^closure\([^:]+\)$/') + ->isEqualTo($result . '') + ->object($reflection = $result->getReflection()) + ->isInstanceOf('ReflectionFunction') + ->string($reflection->getName()) + ->isEqualTo('Hoa\Consistency\Test\Unit\{closure}'); + } + + public function case_form_array_of_class_method() + { + $this + ->when($result = new SUT([__CLASS__, 'strtoupper'])) + ->then + ->string($result('foo')) + ->isEqualTo('FOO') + ->array($result->getValidCallback()) + ->isEqualTo([__CLASS__, 'strtoupper']) + ->string($result->getHash()) + ->isEqualTo('class#' . __CLASS__ . '::strtoupper') + ->isEqualTo($result . '') + ->object($reflection = $result->getReflection()) + ->isInstanceOf('ReflectionMethod') + ->string($reflection->getName()) + ->isEqualTo('strtoupper'); + } + + public function case_form_array_of_object_method() + { + $this + ->when($result = new SUT([$this, 'strtolower'])) + ->then + ->string($result('FOO')) + ->isEqualTo('foo') + ->array($result->getValidCallback()) + ->isEqualTo([$this, 'strtolower']) + ->string($result->getHash()) + ->matches( + '/^object\([^:]+\)#' . + preg_quote(__CLASS__) . + '::strtolower$/' + ) + ->isEqualTo($result . '') + ->object($reflection = $result->getReflection()) + ->isInstanceOf('ReflectionMethod') + ->string($reflection->getName()) + ->isEqualTo('strtolower'); + } + + public function case_form_able_not_a_string() + { + $this + ->exception(function () { + new SUT(__CLASS__, 123); + }) + ->isInstanceOf('Hoa\Consistency\Exception'); + } + + public function case_form_function_not_defined() + { + $this + ->exception(function () { + new SUT('__hoa_test_undefined_function__'); + }) + ->isInstanceOf('Hoa\Consistency\Exception'); + } + + public function case_form_able_cannot_be_deduced() + { + $this + ->given($this->function->method_exists = false) + ->exception(function () { + new SUT($this); + }) + ->isInstanceOf('Hoa\Consistency\Exception'); + } + + public function case_invoke() + { + $this + ->given( + $callable = new SUT( + function ($x, $y, $z) { + return [$x, $y, $z]; + } + ) + ) + ->when($result = $callable(7, [4.2], 'foo')) + ->then + ->array($result) + ->isEqualTo([7, [4.2], 'foo']); + } + + public function case_distribute_arguments() + { + $this + ->given( + $callable = new SUT( + function ($x, $y, $z) { + return [$x, $y, $z]; + } + ) + ) + ->when($result = $callable->distributeArguments([7, [4.2], 'foo'])) + ->then + ->array($result) + ->isEqualTo([7, [4.2], 'foo']); + } + + protected function _get_valid_callback_stream_xxx($argument, $method) + { + $this + ->given( + $stream = new \Mock\Hoa\Stream\IStream\Out(), + $arguments = [$argument], + $xcallable = new SUT($stream) + ) + ->when($result = $xcallable->getValidCallback($arguments)) + ->then + ->array($result) + ->isEqualTo([$stream, $method]); + } + + public function case_get_valid_callback_stream_character() + { + return $this->_get_valid_callback_stream_xxx('f', 'writeCharacter'); + } + + public function case_get_valid_callback_stream_string() + { + return $this->_get_valid_callback_stream_xxx('foo', 'writeString'); + } + + public function case_get_valid_callback_stream_boolean() + { + return $this->_get_valid_callback_stream_xxx(true, 'writeBoolean'); + } + + public function case_get_valid_callback_stream_integer() + { + return $this->_get_valid_callback_stream_xxx(7, 'writeInteger'); + } + + public function case_get_valid_callback_stream_array() + { + return $this->_get_valid_callback_stream_xxx([4, 2], 'writeArray'); + } + + public function case_get_valid_callback_stream_float() + { + return $this->_get_valid_callback_stream_xxx(4.2, 'writeFloat'); + } + + public function case_get_valid_callback_stream_other() + { + return $this->_get_valid_callback_stream_xxx($this, 'writeAll'); + } + + public static function strtoupper($string) + { + return strtoupper($string); + } + + public function strtolower($string) + { + return strtolower($string); + } + + public function __invoke($string) + { + return strtoupper($string); + } + + public function __toString() + { + return 'hello'; + } +} diff --git a/vendor/hoa/consistency/Xcallable.php b/vendor/hoa/consistency/Xcallable.php new file mode 100644 index 0000000000..997b0b6541 --- /dev/null +++ b/vendor/hoa/consistency/Xcallable.php @@ -0,0 +1,316 @@ +method or + * closure, they all have the same behaviour. This callable is an extension of + * native PHP callable (aka callback) to integrate Hoa's structures. + * + * @copyright Copyright © 2007-2017 Hoa community + * @license New BSD License + */ +class Xcallable +{ + /** + * Callback, with the PHP format. + * + * @var mixed + */ + protected $_callback = null; + + /** + * Callable hash. + * + * @var string + */ + protected $_hash = null; + + + + /** + * Build a callback. + * Accepted forms: + * * `'function'`, + * * `'class::method'`, + * * `'class', 'method'`, + * * `$object, 'method'`, + * * `$object, ''`, + * * `function (…) { … }`, + * * `['class', 'method']`, + * * `[$object, 'method']`. + * + * @param mixed $call First callable part. + * @param mixed $able Second callable part (if needed). + */ + public function __construct($call, $able = '') + { + if ($call instanceof \Closure) { + $this->_callback = $call; + + return; + } + + if (!is_string($able)) { + throw new Exception( + 'Bad callback form; the able part must be a string.', + 0 + ); + } + + if ('' === $able) { + if (is_string($call)) { + if (false === strpos($call, '::')) { + if (!function_exists($call)) { + throw new Exception( + 'Bad callback form; function %s does not exist.', + 1, + $call + ); + } + + $this->_callback = $call; + + return; + } + + list($call, $able) = explode('::', $call); + } elseif (is_object($call)) { + if ($call instanceof Stream\IStream\Out) { + $able = null; + } elseif (method_exists($call, '__invoke')) { + $able = '__invoke'; + } else { + throw new Exception( + 'Bad callback form; an object but without a known ' . + 'method.', + 2 + ); + } + } elseif (is_array($call) && isset($call[0])) { + if (!isset($call[1])) { + return $this->__construct($call[0]); + } + + return $this->__construct($call[0], $call[1]); + } else { + throw new Exception( + 'Bad callback form.', + 3 + ); + } + } + + $this->_callback = [$call, $able]; + + return; + } + + /** + * Call the callable. + * + * @param ... + * @return mixed + */ + public function __invoke() + { + $arguments = func_get_args(); + $valid = $this->getValidCallback($arguments); + + return call_user_func_array($valid, $arguments); + } + + /** + * Distribute arguments according to an array. + * + * @param array $arguments Arguments. + * @return mixed + */ + public function distributeArguments(array $arguments) + { + return call_user_func_array([$this, '__invoke'], $arguments); + } + + /** + * Get a valid callback in the PHP meaning. + * + * @param array &$arguments Arguments (could determine method on an + * object if not precised). + * @return mixed + */ + public function getValidCallback(array &$arguments = []) + { + $callback = $this->_callback; + $head = null; + + if (isset($arguments[0])) { + $head = &$arguments[0]; + } + + // If method is undetermined, we find it (we understand event bucket and + // stream). + if (null !== $head && + is_array($callback) && + null === $callback[1]) { + if ($head instanceof Event\Bucket) { + $head = $head->getData(); + } + + switch ($type = gettype($head)) { + case 'string': + if (1 === strlen($head)) { + $method = 'writeCharacter'; + } else { + $method = 'writeString'; + } + + break; + + case 'boolean': + case 'integer': + case 'array': + $method = 'write' . ucfirst($type); + + break; + + case 'double': + $method = 'writeFloat'; + + break; + + default: + $method = 'writeAll'; + $head = $head . "\n"; + } + + $callback[1] = $method; + } + + return $callback; + } + + /** + * Get hash. + * Will produce: + * * function#…; + * * class#…::…; + * * object(…)#…::…; + * * closure(…). + * + * @return string + */ + public function getHash() + { + if (null !== $this->_hash) { + return $this->_hash; + } + + $_ = &$this->_callback; + + if (is_string($_)) { + return $this->_hash = 'function#' . $_; + } + + if (is_array($_)) { + return + $this->_hash = + (is_object($_[0]) + ? 'object(' . spl_object_hash($_[0]) . ')' . + '#' . get_class($_[0]) + : 'class#' . $_[0]) . + '::' . + (null !== $_[1] + ? $_[1] + : '???'); + } + + return $this->_hash = 'closure(' . spl_object_hash($_) . ')'; + } + + /** + * Get appropriated reflection instance. + * + * @param ... + * @return \Reflector + */ + public function getReflection() + { + $arguments = func_get_args(); + $valid = $this->getValidCallback($arguments); + + if (is_string($valid)) { + return new \ReflectionFunction($valid); + } + + if ($valid instanceof \Closure) { + return new \ReflectionFunction($valid); + } + + if (is_array($valid)) { + if (is_string($valid[0])) { + if (false === method_exists($valid[0], $valid[1])) { + return new \ReflectionClass($valid[0]); + } + + return new \ReflectionMethod($valid[0], $valid[1]); + } + + $object = new \ReflectionObject($valid[0]); + + if (null === $valid[1]) { + return $object; + } + + return $object->getMethod($valid[1]); + } + } + + /** + * Return the hash. + * + * @return string + */ + public function __toString() + { + return $this->getHash(); + } +} diff --git a/vendor/hoa/consistency/composer.json b/vendor/hoa/consistency/composer.json new file mode 100644 index 0000000000..9ce777869e --- /dev/null +++ b/vendor/hoa/consistency/composer.json @@ -0,0 +1,45 @@ +{ + "name" : "hoa/consistency", + "description": "The Hoa\\Consistency library.", + "type" : "library", + "keywords" : ["library", "consistency", "autoloader", "entity", "flex", + "keyword", "callable"], + "homepage" : "https://hoa-project.net/", + "license" : "BSD-3-Clause", + "authors" : [ + { + "name" : "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name" : "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "support": { + "email" : "support@hoa-project.net", + "irc" : "irc://chat.freenode.net/hoaproject", + "forum" : "https://users.hoa-project.net/", + "docs" : "https://central.hoa-project.net/Documentation/Library/Consistency", + "source": "https://central.hoa-project.net/Resource/Library/Consistency" + }, + "require": { + "php" : ">=5.5.0", + "hoa/exception": "~1.0" + }, + "require-dev": { + "hoa/stream": "~1.0", + "hoa/test" : "~2.0" + }, + "autoload": { + "psr-4": { + "Hoa\\Consistency\\": "." + }, + "files": ["Prelude.php"] + }, + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + } +} diff --git a/vendor/hoa/event/.State b/vendor/hoa/event/.State new file mode 100644 index 0000000000..a604de473a --- /dev/null +++ b/vendor/hoa/event/.State @@ -0,0 +1 @@ +finalized diff --git a/vendor/hoa/event/.gitignore b/vendor/hoa/event/.gitignore new file mode 100644 index 0000000000..4fbb073c49 --- /dev/null +++ b/vendor/hoa/event/.gitignore @@ -0,0 +1,2 @@ +/vendor/ +/composer.lock diff --git a/vendor/hoa/event/Bucket.php b/vendor/hoa/event/Bucket.php new file mode 100644 index 0000000000..968350da92 --- /dev/null +++ b/vendor/hoa/event/Bucket.php @@ -0,0 +1,136 @@ +setData($data); + + return; + } + + /** + * Send this object on the event channel. + * + * @param string $eventId Event ID. + * @param \Hoa\Event\Source $source Source. + * @return void + */ + public function send($eventId, Source $source) + { + return Event::notify($eventId, $source, $this); + } + + /** + * Set source. + * + * @param \Hoa\Event\Source $source Source. + * @return \Hoa\Event\Source + */ + public function setSource(Source $source) + { + $old = $this->_source; + $this->_source = $source; + + return $old; + } + + /** + * Get source. + * + * @return \Hoa\Event\Source + */ + public function getSource() + { + return $this->_source; + } + + /** + * Set data. + * + * @param mixed $data Data. + * @return mixed + */ + public function setData($data) + { + $old = $this->_data; + $this->_data = $data; + + return $old; + } + + /** + * Get data. + * + * @return mixed + */ + public function getData() + { + return $this->_data; + } +} diff --git a/vendor/hoa/event/CHANGELOG.md b/vendor/hoa/event/CHANGELOG.md new file mode 100644 index 0000000000..7e646a0e98 --- /dev/null +++ b/vendor/hoa/event/CHANGELOG.md @@ -0,0 +1,44 @@ +# 1.17.01.13 + + * Quality: Happy new year! (Alexis von Glasow, 2017-01-11T23:09:35+01:00) + +# 1.16.11.19 + + * Documentation: New `README.md` file. (Ivan Enderlin, 2016-10-18T16:34:43+02:00) + * Documentation: Update `support` properties. (Ivan Enderlin, 2016-10-05T20:36:30+02:00) + +# 1.16.03.15 + + * Fix a typo (Metalaka, 2016-01-28T09:05:40+01:00) + * CHANGELOG: Add a missing newline. (Ivan Enderlin, 2016-01-11T09:37:32+01:00) + +# 1.16.01.11 + + * Quality: Drop PHP5.4. (Ivan Enderlin, 2016-01-11T09:15:26+01:00) + * Quality: Run devtools:cs. (Ivan Enderlin, 2016-01-09T09:01:10+01:00) + * Core: Remove `Hoa\Core`. (Ivan Enderlin, 2016-01-09T08:14:54+01:00) + * Consistency: Use `Hoa\Consistency`. (Ivan Enderlin, 2015-12-08T11:10:00+01:00) + * Documentation: Fix typos. (Ivan Enderlin, 2015-11-23T22:05:56+01:00) + * Exception: Use `Hoa\Exception`. (Ivan Enderlin, 2015-11-20T07:40:34+01:00) + +# 0.15.11.23 + + * Documentation: Fix typos. (Ivan Enderlin, 2015-11-23T22:05:56+01:00) + * Exception: Use `Hoa\Exception`. (Ivan Enderlin, 2015-11-20T07:40:34+01:00) + * Test: Fix a conflict between 2 test suites. (Ivan Enderlin, 2015-11-23T21:29:28+01:00) + * Test: Write test suite for `Hoa\Event\Listens`. (Ivan Enderlin, 2015-11-23T21:25:49+01:00) + * Listener: Add the `Listens` trait. (Ivan Enderlin, 2015-11-20T06:45:11+01:00) + * Documentation: Fix a typo. (Ivan Enderlin, 2015-11-23T13:01:56+01:00) + * Improve readability by adding constants to registered events container. (Metalaka, 2015-11-20T19:53:32+01:00) + * Add a `.gitignore` file. (Metalaka, 2015-11-20T19:37:52+01:00) + * README: Complete description and add usage. (Ivan Enderlin, 2015-11-13T08:43:08+01:00) + * Test: Write test suite for `Hoa\Event\Event`. (Ivan Enderlin, 2015-11-11T17:04:41+01:00) + * Test: Write test suite for `Hoa\Event\Exception`. (Ivan Enderlin, 2015-11-11T16:46:12+01:00) + * Composer: Add a keyword. (Ivan Enderlin, 2015-11-11T13:38:35+01:00) + * Test: Write test suite for `Hoa\Event\Listener`. (Ivan Enderlin, 2015-11-11T13:27:40+01:00) + * Test: Write test suite for `Hoa\Event\Source`. (Ivan Enderlin, 2015-11-10T21:56:37+01:00) + * Test: Write test suite for `Hoa\Event\Listenable`. (Ivan Enderlin, 2015-11-10T21:56:24+01:00) + * Test: Write test suite for `Hoa\Event\Bucket`. (Ivan Enderlin, 2015-11-10T21:55:45+01:00) + * Split from `Hoa\Core`. (Ivan Enderlin, 2015-11-10T21:28:31+01:00) + +(first snapshot) diff --git a/vendor/hoa/event/Event.php b/vendor/hoa/event/Event.php new file mode 100644 index 0000000000..23b3292dd6 --- /dev/null +++ b/vendor/hoa/event/Event.php @@ -0,0 +1,266 @@ + new self(), + self::KEY_SOURCE => null + ]; + } + + return self::$_register[$eventId][self::KEY_EVENT]; + } + + /** + * Declare a new object in the observable collection. + * Note: Hoa's libraries use hoa://Event/AnID for their observable objects; + * + * @param string $eventId Event ID. + * @param \Hoa\Event\Source|string $source Observable object or class. + * @return void + * @throws \Hoa\Event\Exception + */ + public static function register($eventId, $source) + { + if (true === self::eventExists($eventId)) { + throw new Exception( + 'Cannot redeclare an event with the same ID, i.e. the event ' . + 'ID %s already exists.', + 0, + $eventId + ); + } + + if (is_object($source) && !($source instanceof Source)) { + throw new Exception( + 'The source must implement \Hoa\Event\Source ' . + 'interface; given %s.', + 1, + get_class($source) + ); + } else { + $reflection = new \ReflectionClass($source); + + if (false === $reflection->implementsInterface('\Hoa\Event\Source')) { + throw new Exception( + 'The source must implement \Hoa\Event\Source ' . + 'interface; given %s.', + 2, + $source + ); + } + } + + if (!isset(self::$_register[$eventId][self::KEY_EVENT])) { + self::$_register[$eventId][self::KEY_EVENT] = new self(); + } + + self::$_register[$eventId][self::KEY_SOURCE] = $source; + + return; + } + + /** + * Undeclare an object in the observable collection. + * + * @param string $eventId Event ID. + * @param bool $hard If false, just delete the source, else, + * delete source and attached callables. + * @return void + */ + public static function unregister($eventId, $hard = false) + { + if (false !== $hard) { + unset(self::$_register[$eventId]); + } else { + self::$_register[$eventId][self::KEY_SOURCE] = null; + } + + return; + } + + /** + * Attach an object to an event. + * It can be a callable or an accepted callable form (please, see the + * \Hoa\Consistency\Xcallable class). + * + * @param mixed $callable Callable. + * @return \Hoa\Event\Event + */ + public function attach($callable) + { + $callable = xcallable($callable); + $this->_callable[$callable->getHash()] = $callable; + + return $this; + } + + /** + * Detach an object to an event. + * Please see $this->attach() method. + * + * @param mixed $callable Callable. + * @return \Hoa\Event\Event + */ + public function detach($callable) + { + unset($this->_callable[xcallable($callable)->getHash()]); + + return $this; + } + + /** + * Check if at least one callable is attached to an event. + * + * @return bool + */ + public function isListened() + { + return !empty($this->_callable); + } + + /** + * Notify, i.e. send data to observers. + * + * @param string $eventId Event ID. + * @param \Hoa\Event\Source $source Source. + * @param \Hoa\Event\Bucket $data Data. + * @return void + * @throws \Hoa\Event\Exception + */ + public static function notify($eventId, Source $source, Bucket $data) + { + if (false === self::eventExists($eventId)) { + throw new Exception( + 'Event ID %s does not exist, cannot send notification.', + 3, + $eventId + ); + } + + $data->setSource($source); + $event = self::getEvent($eventId); + + foreach ($event->_callable as $callable) { + $callable($data); + } + + return; + } + + /** + * Check whether an event exists. + * + * @param string $eventId Event ID. + * @return bool + */ + public static function eventExists($eventId) + { + return + array_key_exists($eventId, self::$_register) && + self::$_register[$eventId][self::KEY_SOURCE] !== null; + } +} + +/** + * Flex entity. + */ +Consistency::flexEntity('Hoa\Event\Event'); diff --git a/vendor/hoa/event/Exception.php b/vendor/hoa/event/Exception.php new file mode 100644 index 0000000000..94b92f70f6 --- /dev/null +++ b/vendor/hoa/event/Exception.php @@ -0,0 +1,51 @@ +_source = $source; + $this->addIds($ids); + + return; + } + + /** + * Add acceptable ID (or reset). + * + * @param array $ids Accepted ID. + * @return void + */ + public function addIds(array $ids) + { + foreach ($ids as $id) { + $this->_callables[$id] = []; + } + + return; + } + + /** + * Attach a callable to a listenable component. + * + * @param string $listenerId Listener ID. + * @param mixed $callable Callable. + * @return \Hoa\Event\Listener + * @throws \Hoa\Event\Exception + */ + public function attach($listenerId, $callable) + { + if (false === $this->listenerExists($listenerId)) { + throw new Exception( + 'Cannot listen %s because it is not defined.', + 0, + $listenerId + ); + } + + $callable = xcallable($callable); + $this->_callables[$listenerId][$callable->getHash()] = $callable; + + return $this; + } + + /** + * Detach a callable from a listenable component. + * + * @param string $listenerId Listener ID. + * @param mixed $callable Callable. + * @return \Hoa\Event\Listener + */ + public function detach($listenerId, $callable) + { + unset($this->_callables[$listenerId][xcallable($callable)->getHash()]); + + return $this; + } + + /** + * Detach all callables from a listenable component. + * + * @param string $listenerId Listener ID. + * @return \Hoa\Event\Listener + */ + public function detachAll($listenerId) + { + unset($this->_callables[$listenerId]); + + return $this; + } + + /** + * Check if a listener exists. + * + * @param string $listenerId Listener ID. + * @return bool + */ + public function listenerExists($listenerId) + { + return array_key_exists($listenerId, $this->_callables); + } + + /** + * Send/fire a bucket to a listener. + * + * @param string $listenerId Listener ID. + * @param \Hoa\Event\Bucket $data Data. + * @return array + * @throws \Hoa\Event\Exception + */ + public function fire($listenerId, Bucket $data) + { + if (false === $this->listenerExists($listenerId)) { + throw new Exception( + 'Cannot fire on %s because it is not defined.', + 1, + $listenerId + ); + } + + $data->setSource($this->_source); + $out = []; + + foreach ($this->_callables[$listenerId] as $callable) { + $out[] = $callable($data); + } + + return $out; + } +} diff --git a/vendor/hoa/event/Listens.php b/vendor/hoa/event/Listens.php new file mode 100644 index 0000000000..83f62231da --- /dev/null +++ b/vendor/hoa/event/Listens.php @@ -0,0 +1,106 @@ +getListener(); + + if (null === $listener) { + throw new Exception( + 'Cannot attach a callable to the listener %s because ' . + 'it has not been initialized yet.', + 0, + get_class($this) + ); + } + + $listener->attach($listenerId, $callable); + + return $this; + } + + /** + * Set listener. + * + * @param \Hoa\Event\Listener $listener Listener. + * @return \Hoa\Event\Listener + */ + protected function setListener(Listener $listener) + { + $old = $this->_listener; + $this->_listener = $listener; + + return $old; + } + + /** + * Get listener. + * + * @return \Hoa\Event\Listener + */ + protected function getListener() + { + return $this->_listener; + } +} diff --git a/vendor/hoa/event/README.md b/vendor/hoa/event/README.md new file mode 100644 index 0000000000..b5b8ed583c --- /dev/null +++ b/vendor/hoa/event/README.md @@ -0,0 +1,161 @@ +

+ Hoa +

+ +--- + +

+ Build status + Code coverage + Packagist + License +

+

+ Hoa is a modular, extensible and + structured set of PHP libraries.
+ Moreover, Hoa aims at being a bridge between industrial and research worlds. +

+ +# Hoa\Event + +[![Help on IRC](https://img.shields.io/badge/help-%23hoaproject-ff0066.svg)](https://webchat.freenode.net/?channels=#hoaproject) +[![Help on Gitter](https://img.shields.io/badge/help-gitter-ff0066.svg)](https://gitter.im/hoaproject/central) +[![Documentation](https://img.shields.io/badge/documentation-hack_book-ff0066.svg)](https://central.hoa-project.net/Documentation/Library/Event) +[![Board](https://img.shields.io/badge/organisation-board-ff0066.svg)](https://waffle.io/hoaproject/event) + +This library allows to use events and listeners in PHP. This is an observer +design-pattern implementation. + +[Learn more](https://central.hoa-project.net/Documentation/Library/Event). + +## Installation + +With [Composer](https://getcomposer.org/), to include this library into +your dependencies, you need to +require [`hoa/event`](https://packagist.org/packages/hoa/event): + +```sh +$ composer require hoa/event '~1.0' +``` + +For more installation procedures, please read [the Source +page](https://hoa-project.net/Source.html). + +## Testing + +Before running the test suites, the development dependencies must be installed: + +```sh +$ composer install +``` + +Then, to run all the test suites: + +```sh +$ vendor/bin/hoa test:run +``` + +For more information, please read the [contributor +guide](https://hoa-project.net/Literature/Contributor/Guide.html). + +## Quick usage + +We propose a quick overview of how to use events and listeners. + +### Events + +An event is: + * **Asynchronous** when registering, because the observable may not exist yet + while observers start to observe, + * **Anonymous** when using, because the observable has no idea how many and + what observers are observing, + * It aims at a **large** diffusion of data through isolated components. + Wherever is the observable, we can observe its data. + +In Hoa, an event channel has the following form: +`hoa://Event/LibraryName/AnId:pseudo-class#anAnchor`. For instance, the +`hoa://Event/Exception` channel contains all exceptions that have been thrown. +The `hoa://Event/Stream/StreamName:close-before` contains all streams that are +about to close. Thus, the following example will observe all thrown exceptions: + +```php +Hoa\Event\Event::getEvent('hoa://Event/Exception')->attach( + function (Hoa\Event\Bucket $bucket) { + var_dump( + $bucket->getSource(), + $bucket->getData() + ); + } +); +``` + +Because `attach` expects a callable and because Hoa's callable implementation is +smart, we can directly attach a stream to an event, like: + +```php +Hoa\Event\Event::getEvent('hoa://Event/Exception')->attach( + new Hoa\File\Write('Foo.log') +); +``` + +This way, all exceptions will be printed on the `Foo.log` file. + +### Listeners + +Contrary to an event, a listener is: + * **Synchronous** when registering, because the observable must exist before + observers can observe, + * **Identified** when using, because the observable knows how many observers + are observing, + * It aims at a **close** diffusion of data. The observers must have an access + to the observable to observe. + +The `Hoa\Event\Listenable` interface requires the `on` method to be present to +register a listener to a listener ID. For instance, the following example +listens the `message` listener ID, i.e. when a message is received by the +WebSocket server, the closure is executed: + +```php +$server = new Hoa\Websocket\Server(…); +$server->on('message', function (Hoa\Event\Bucket $bucket) { + var_dump( + $bucket->getSource(), + $bucket->getData() + ); +}); +``` + +## Documentation + +The +[hack book of `Hoa\Event`](https://central.hoa-project.net/Documentation/Library/Event) contains +detailed information about how to use this library and how it works. + +To generate the documentation locally, execute the following commands: + +```sh +$ composer require --dev hoa/devtools +$ vendor/bin/hoa devtools:documentation --open +``` + +More documentation can be found on the project's website: +[hoa-project.net](https://hoa-project.net/). + +## Getting help + +There are mainly two ways to get help: + + * On the [`#hoaproject`](https://webchat.freenode.net/?channels=#hoaproject) + IRC channel, + * On the forum at [users.hoa-project.net](https://users.hoa-project.net). + +## Contribution + +Do you want to contribute? Thanks! A detailed [contributor +guide](https://hoa-project.net/Literature/Contributor/Guide.html) explains +everything you need to know. + +## License + +Hoa is under the New BSD License (BSD-3-Clause). Please, see +[`LICENSE`](https://hoa-project.net/LICENSE) for details. diff --git a/vendor/hoa/event/Source.php b/vendor/hoa/event/Source.php new file mode 100644 index 0000000000..d1510ca5e7 --- /dev/null +++ b/vendor/hoa/event/Source.php @@ -0,0 +1,49 @@ +when($result = new SUT('foo')) + ->then + ->object($result) + ->isInstanceOf('Hoa\Event\Bucket') + ->string($result->getData()) + ->isEqualTo('foo'); + } + + public function case_send() + { + $self = $this; + + $this + ->given( + $eventId = 'hoa://Event/Test', + $source = new \Mock\Hoa\Event\Source(), + LUT::register($eventId, $source), + + $bucket = new SUT('foo'), + + LUT::getEvent($eventId)->attach( + function (SUT $receivedBucket) use ($self, $bucket, &$called) { + $called = true; + + $self + ->object($receivedBucket) + ->isIdenticalTo($bucket); + } + ) + ) + ->when($result = $bucket->send($eventId, $source)) + ->then + ->variable($result) + ->isNull() + ->boolean($called) + ->isTrue(); + } + + public function case_set_source() + { + $this + ->given( + $bucket = new SUT(), + $sourceA = new \Mock\Hoa\Event\Source() + ) + ->when($result = $bucket->setSource($sourceA)) + ->then + ->variable($result) + ->isNull() + ->object($bucket->getSource()) + ->isIdenticalTo($sourceA) + + ->given($sourceB = new \Mock\Hoa\Event\Source()) + ->when($result = $bucket->setSource($sourceB)) + ->then + ->object($result) + ->isIdenticalTo($sourceA) + ->object($bucket->getSource()) + ->isIdenticalTo($sourceB); + } + + public function case_set_data() + { + $this + ->given( + $bucket = new SUT(), + $datumA = 'foo' + ) + ->when($result = $bucket->setData($datumA)) + ->then + ->variable($result) + ->isNull() + ->string($bucket->getData()) + ->isEqualTo($datumA) + + ->given($datumB = 'bar') + ->when($result = $bucket->setData($datumB)) + ->then + ->string($result) + ->isEqualTo($datumA) + ->string($bucket->getData()) + ->isEqualTo($datumB); + } +} diff --git a/vendor/hoa/event/Test/Unit/Event.php b/vendor/hoa/event/Test/Unit/Event.php new file mode 100644 index 0000000000..daf03eb845 --- /dev/null +++ b/vendor/hoa/event/Test/Unit/Event.php @@ -0,0 +1,300 @@ +given($eventId = 'hoa://Event/Test') + ->when($result = SUT::getEvent($eventId)) + ->then + ->object($result) + ->isInstanceOf('Hoa\Event\Event') + ->object(SUT::getEvent($eventId)) + ->isIdenticalTo($result); + } + + public function case_register_source_instance() + { + $this + ->given( + $eventId = 'hoa://Event/Test', + $source = new \Mock\Hoa\Event\Source() + ) + ->when($result = SUT::register($eventId, $source)) + ->then + ->variable($result) + ->isNull() + ->boolean(SUT::eventExists($eventId)) + ->isTrue(); + } + + public function case_register_source_name() + { + $this + ->given( + $eventId = 'hoa://Event/Test', + $source = 'Mock\Hoa\Event\Source' + ) + ->when($result = SUT::register($eventId, $source)) + ->then + ->variable($result) + ->isNull() + ->boolean(SUT::eventExists($eventId)) + ->isTrue(); + } + + public function case_register_redeclare() + { + $this + ->given( + $eventId = 'hoa://Event/Test', + $source = new \Mock\Hoa\Event\Source(), + SUT::register($eventId, $source) + ) + ->exception(function () use ($eventId, $source) { + SUT::register($eventId, $source); + }) + ->isInstanceOf('Hoa\Event\Exception'); + } + + public function case_register_not_a_source_instance() + { + $this + ->given( + $eventId = 'hoa://Event/Test', + $source = new \StdClass() + ) + ->exception(function () use ($eventId, $source) { + $result = SUT::register($eventId, $source); + }) + ->isInstanceOf('Hoa\Event\Exception'); + } + + public function case_register_not_a_source_name() + { + $this + ->given( + $eventId = 'hoa://Event/Test', + $source = 'StdClass' + ) + ->exception(function () use ($eventId, $source) { + $result = SUT::register($eventId, $source); + }) + ->isInstanceOf('Hoa\Event\Exception'); + } + + public function case_unregister() + { + $this + ->given( + $eventId = 'hoa://Event/Test', + $source = new \Mock\Hoa\Event\Source(), + SUT::register($eventId, $source) + ) + ->when($result = SUT::unregister($eventId)) + ->then + ->boolean(SUT::eventExists($eventId)) + ->isFalse(); + } + + public function case_unregister_hard() + { + $this + ->given( + $eventId = 'hoa://Event/Test', + $source = new \Mock\Hoa\Event\Source(), + SUT::register($eventId, $source), + $event = SUT::getEvent($eventId) + ) + ->when($result = SUT::unregister($eventId, true)) + ->then + ->boolean(SUT::eventExists($eventId)) + ->isFalse() + ->object(SUT::getEvent($eventId)) + ->isNotIdenticalTo($event); + } + + public function case_unregister_not_registered() + { + $this + ->given($eventId = 'hoa://Event/Test') + ->when($result = SUT::unregister($eventId)) + ->then + ->variable($result) + ->isNull(); + } + + public function case_attach() + { + $this + ->given( + $event = SUT::getEvent('hoa://Event/Test'), + $callable = function () { } + ) + ->when($result = $event->attach($callable)) + ->then + ->object($result) + ->isIdenticalTo($event) + ->boolean($event->isListened()) + ->isTrue(); + } + + public function case_detach() + { + $this + ->given( + $event = SUT::getEvent('hoa://Event/Test'), + $callable = function () { }, + $event->attach($callable) + ) + ->when($result = $event->detach($callable)) + ->then + ->object($result) + ->isIdenticalTo($event) + ->boolean($event->isListened()) + ->isFalse(); + } + + public function case_detach_unattached() + { + $this + ->given( + $event = SUT::getEvent('hoa://Event/Test'), + $callable = function () { } + ) + ->when($result = $event->detach($callable)) + ->then + ->object($result) + ->isIdenticalTo($event) + ->boolean($event->isListened()) + ->isFalse(); + } + + public function case_is_listened() + { + $this + ->given($event = SUT::getEvent('hoa://Event/Test')) + ->when($result = $event->isListened()) + ->then + ->boolean($event->isListened()) + ->isFalse(); + } + + public function case_notify() + { + $self = $this; + + $this + ->given( + $eventId = 'hoa://Event/Test', + $source = new \Mock\Hoa\Event\Source(), + $bucket = new LUT\Bucket(), + + SUT::register($eventId, $source), + SUT::getEvent($eventId)->attach( + function (LUT\Bucket $receivedBucket) use ($self, $source, $bucket, &$called) { + $called = true; + + $this + ->object($receivedBucket) + ->isIdenticalTo($bucket) + ->object($receivedBucket->getSource()) + ->isIdenticalTo($source); + } + ) + ) + ->when($result = SUT::notify($eventId, $source, $bucket)) + ->then + ->variable($result) + ->isNull() + ->boolean($called) + ->isTrue(); + } + + public function case_notify_unregistered_event_id() + { + $this + ->given( + $eventId = 'hoa://Event/Test', + $source = new \Mock\Hoa\Event\Source(), + $data = new LUT\Bucket() + ) + ->exception(function () use ($eventId, $source, $data) { + SUT::notify($eventId, $source, $data); + }) + ->isInstanceOf('Hoa\Event\Exception'); + } + + public function case_event_exists() + { + $this + ->given( + $eventId = 'hoa://Event/Test', + $source = new \Mock\Hoa\Event\Source(), + SUT::register($eventId, $source) + ) + ->when($result = SUT::eventExists($eventId)) + ->then + ->boolean($result) + ->isTrue(); + } + + public function case_event_not_exists() + { + $this + ->given($eventId = 'hoa://Event/Test') + ->when($result = SUT::eventExists($eventId)) + ->then + ->boolean($result) + ->isFalse(); + } +} diff --git a/vendor/hoa/event/Test/Unit/Exception.php b/vendor/hoa/event/Test/Unit/Exception.php new file mode 100644 index 0000000000..e24f4af06e --- /dev/null +++ b/vendor/hoa/event/Test/Unit/Exception.php @@ -0,0 +1,60 @@ +when($result = new SUT('foo', 0)) + ->then + ->object($result) + ->isInstanceOf('Hoa\Exception\Exception'); + } +} diff --git a/vendor/hoa/event/Test/Unit/Listenable.php b/vendor/hoa/event/Test/Unit/Listenable.php new file mode 100644 index 0000000000..4ba1ca2c00 --- /dev/null +++ b/vendor/hoa/event/Test/Unit/Listenable.php @@ -0,0 +1,59 @@ +when($result = new \Mock\Hoa\Event\Listenable()) + ->then + ->object($result) + ->isInstanceOf('Hoa\Event\Listenable'); + } +} diff --git a/vendor/hoa/event/Test/Unit/Listener.php b/vendor/hoa/event/Test/Unit/Listener.php new file mode 100644 index 0000000000..8216302d42 --- /dev/null +++ b/vendor/hoa/event/Test/Unit/Listener.php @@ -0,0 +1,240 @@ +given( + $source = new \Mock\Hoa\Event\Listenable(), + $ids = ['foo', 'bar', 'baz'] + ) + ->when($result = new SUT($source, $ids)) + ->then + ->object($result) + ->isInstanceOf('Hoa\Event\Listener') + ->boolean($result->listenerExists('foo')) + ->isTrue() + ->boolean($result->listenerExists('bar')) + ->isTrue() + ->boolean($result->listenerExists('baz')) + ->isTrue(); + } + + public function case_attach() + { + $this + ->given( + $source = new \Mock\Hoa\Event\Listenable(), + $listenerId = 'foo', + $listener = new SUT($source, ['foo', 'bar']), + $callable = function () { + return 42; + } + ) + ->when($result = $listener->attach($listenerId, $callable)) + ->then + ->object($result) + ->isIdenticalTo($listener) + ->array($listener->fire($listenerId, new LUT\Bucket())) + ->isEqualTo([42]); + } + + public function case_attach_to_an_undefined_listener() + { + $this + ->given( + $source = new \Mock\Hoa\Event\Listenable(), + $listenerId = 'bar', + $listener = new SUT($source, ['foo', 'baz']), + $callable = function () { } + ) + ->exception(function () use ($listener, $listenerId, $callable) { + $listener->attach($listenerId, $callable); + }) + ->isInstanceOf('Hoa\Event\Exception'); + } + + public function case_detach() + { + $this + ->given( + $source = new \Mock\Hoa\Event\Listenable(), + $listenerId = 'foo', + $listener = new SUT($source, ['foo', 'bar']), + $callable = function () { + return 42; + }, + $listener->attach($listenerId, $callable) + ) + ->when($result = $listener->detach($listenerId, $callable)) + ->then + ->object($result) + ->isIdenticalTo($listener) + ->array($listener->fire($listenerId, new LUT\Bucket())) + ->isEmpty(); + } + + public function case_detach_an_undefined_listener() + { + $this + ->given( + $source = new \Mock\Hoa\Event\Listenable(), + $listenerId = 'bar', + $listener = new SUT($source, ['foo', 'baz']), + $callable = function () { } + ) + ->when($result = $listener->detach($listenerId, $callable)) + ->then + ->object($result) + ->isIdenticalTo($listener); + } + + public function case_detach_all() + { + $this + ->given( + $source = new \Mock\Hoa\Event\Listenable(), + $listenerId = 'foo', + $listener = new SUT($source, ['foo', 'bar']) + ) + ->when($result = $listener->detachAll($listenerId)) + ->then + ->object($result) + ->isIdenticalTo($listener) + ->boolean($listener->listenerExists($listenerId)) + ->isFalse(); + } + + public function case_detach_all_with_an_undefined_listener() + { + $this + ->given( + $source = new \Mock\Hoa\Event\Listenable(), + $listenerId = 'bar', + $listener = new SUT($source, ['foo', 'baz']) + ) + ->when($result = $listener->detachAll($listenerId)) + ->then + ->object($result) + ->isIdenticalTo($listener); + } + + public function case_listener_exists() + { + $this + ->given( + $source = new \Mock\Hoa\Event\Listenable(), + $ids = [], + $listener = new SUT($source, $ids) + ) + ->when($listener->addIds(['foo'])) + ->then + ->boolean($listener->listenerExists('foo')) + ->isTrue() + ->boolean($listener->listenerExists('bar')) + ->isFalse() + + ->when($listener->addIds(['bar'])) + ->then + ->boolean($listener->listenerExists('bar')) + ->isTrue(); + } + + public function case_fire() + { + $self = $this; + + $this + ->given( + $source = new \Mock\Hoa\Event\Listenable(), + $ids = ['foo', 'bar'], + $listener = new SUT($source, $ids), + + $listenerId = 'foo', + $bucket = new LUT\Bucket(), + $listener->attach( + $listenerId, + function (LUT\Bucket $receivedBucket) use ($self, $bucket, $source, &$called) { + $called = true; + + $self + ->object($receivedBucket) + ->isIdenticalTo($bucket) + ->object($receivedBucket->getSource()) + ->isIdenticalTo($source); + + return 42; + } + ) + ) + ->when($result = $listener->fire($listenerId, $bucket)) + ->then + ->array($result) + ->isEqualTo([42]) + ->boolean($called) + ->isTrue(); + } + + public function case_fire_an_undefined_listenerId() + { + $this + ->given( + $source = new \Mock\Hoa\Event\Listenable(), + $ids = [], + $listener = new SUT($source, $ids) + ) + ->exception(function () use ($listener) { + $listener->fire('foo', new LUT\Bucket()); + }) + ->isInstanceOf('Hoa\Event\Exception'); + } +} diff --git a/vendor/hoa/event/Test/Unit/Listens.php b/vendor/hoa/event/Test/Unit/Listens.php new file mode 100644 index 0000000000..8978c82757 --- /dev/null +++ b/vendor/hoa/event/Test/Unit/Listens.php @@ -0,0 +1,139 @@ +given( + $listenable = new _Listenable(), + $listener = new LUT\Listener($listenable, ['foo']) + ) + ->when($result = $listenable->_setListener($listener)) + ->then + ->variable($result) + ->isNull(); + } + + public function case_get_listener() + { + $this + ->given( + $listenable = new _Listenable(), + $listener = new LUT\Listener($listenable, ['foo']), + $listenable->_setListener($listener) + ) + ->when($result = $listenable->_getListener()) + ->then + ->object($result) + ->isIdenticalTo($listener); + } + + public function case_on() + { + $this + ->given( + $listenable = new _Listenable(), + $listener = new LUT\Listener($listenable, ['foo']), + $listenable->_setListener($listener), + $callable = function () use (&$called) { + $called = true; + + return 42; + } + ) + ->when($result = $listenable->on('foo', $callable)) + ->then + ->object($result) + ->isIdenticalTo($listenable) + + ->when($listenable->doSomethingThatFires()) + ->then + ->boolean($called) + ->isTrue(); + } + + public function case_on_unregistered_listener() + { + $this + ->given( + $listenable = new _Listenable(), + $listener = new LUT\Listener($listenable, ['foo']), + $listenable->_setListener($listener) + ) + ->exception(function () use ($listenable) { + $listenable->on('bar', null); + }) + ->isInstanceOf('Hoa\Event\Exception'); + } +} + +class _Listenable implements LUT\Listenable +{ + use SUT; + + public function _setListener(LUT\Listener $listener) + { + return $this->setListener($listener); + } + + public function _getListener() + { + return $this->getListener(); + } + + public function doSomethingThatFires() + { + $this->getListener()->fire('foo', new LUT\Bucket('bar')); + + return; + } +} diff --git a/vendor/hoa/event/Test/Unit/Source.php b/vendor/hoa/event/Test/Unit/Source.php new file mode 100644 index 0000000000..1d41880cb9 --- /dev/null +++ b/vendor/hoa/event/Test/Unit/Source.php @@ -0,0 +1,59 @@ +when($result = new \Mock\Hoa\Event\Source()) + ->then + ->object($result) + ->isInstanceOf('Hoa\Event\Source'); + } +} diff --git a/vendor/hoa/event/composer.json b/vendor/hoa/event/composer.json new file mode 100644 index 0000000000..293515945a --- /dev/null +++ b/vendor/hoa/event/composer.json @@ -0,0 +1,42 @@ +{ + "name" : "hoa/event", + "description": "The Hoa\\Event library.", + "type" : "library", + "keywords" : ["library", "event", "listener", "observer"], + "homepage" : "https://hoa-project.net/", + "license" : "BSD-3-Clause", + "authors" : [ + { + "name" : "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name" : "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "support": { + "email" : "support@hoa-project.net", + "irc" : "irc://chat.freenode.net/hoaproject", + "forum" : "https://users.hoa-project.net/", + "docs" : "https://central.hoa-project.net/Documentation/Library/Event", + "source": "https://central.hoa-project.net/Resource/Library/Event" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception" : "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "autoload": { + "psr-4": { + "Hoa\\Event\\": "." + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + } +} diff --git a/vendor/hoa/exception/.State b/vendor/hoa/exception/.State new file mode 100644 index 0000000000..a604de473a --- /dev/null +++ b/vendor/hoa/exception/.State @@ -0,0 +1 @@ +finalized diff --git a/vendor/hoa/exception/.gitignore b/vendor/hoa/exception/.gitignore new file mode 100644 index 0000000000..4fbb073c49 --- /dev/null +++ b/vendor/hoa/exception/.gitignore @@ -0,0 +1,2 @@ +/vendor/ +/composer.lock diff --git a/vendor/hoa/exception/CHANGELOG.md b/vendor/hoa/exception/CHANGELOG.md new file mode 100644 index 0000000000..5cdd72ea64 --- /dev/null +++ b/vendor/hoa/exception/CHANGELOG.md @@ -0,0 +1,30 @@ +# 1.17.01.16 + + * Quality: Happy new year! (Ivan Enderlin, 2017-01-16T08:52:04+01:00) + +# 1.16.11.08 + + * Documentation: New `README.md` file. (Ivan Enderlin, 2016-10-19T16:31:55+02:00) + * Documentation: Update `support` properties. (Ivan Enderlin, 2016-10-05T20:39:14+02:00) + +# 1.16.01.11 + + * Quality: Drop PHP5.4. (Ivan Enderlin, 2016-01-11T09:15:26+01:00) + * Quality: Run devtools:cs. (Ivan Enderlin, 2016-01-09T09:01:35+01:00) + * Core: Remove `Hoa\Core`. (Ivan Enderlin, 2016-01-09T08:16:03+01:00) + * Consistency: Use `Hoa\Consistency`. (Ivan Enderlin, 2015-12-08T11:11:27+01:00) + +# 0.15.11.23 + + * Fix phpDoc and a mistake on a static call. (Metalaka, 2015-11-21T17:44:35+01:00) + * Add a `.gitignore` file. (Metalaka, 2015-11-21T17:39:21+01:00) + * Test: Add test cases for the uncaught handler. (Ivan Enderlin, 2015-11-18T21:48:20+01:00) + * Idle: Add uncaught handler. (Ivan Enderlin, 2015-11-18T21:47:40+01:00) + * README: Add a better description and new usages. (Ivan Enderlin, 2015-11-18T21:36:03+01:00) + * Test: Write test suite of `Hoa\Exception\Group`. (Ivan Enderlin, 2015-11-18T08:28:04+01:00) + * Test: Write test suite of `Hoa\Exception\Error`. (Ivan Enderlin, 2015-11-17T22:30:14+01:00) + * Test: Write test suite of `…\Exception\Exception`. (Ivan Enderlin, 2015-11-17T22:03:31+01:00) + * Test: Write test suite of `Hoa\Exception\Idle`. (Ivan Enderlin, 2015-11-17T21:41:07+01:00) + * Split from `Hoa\Core`. (Ivan Enderlin, 2015-11-13T08:58:45+01:00) + +(first snapshot) diff --git a/vendor/hoa/exception/Error.php b/vendor/hoa/exception/Error.php new file mode 100644 index 0000000000..898aaf89d0 --- /dev/null +++ b/vendor/hoa/exception/Error.php @@ -0,0 +1,100 @@ +file = $file; + $this->line = $line; + $this->_trace = $trace; + + parent::__construct($message, $code); + + return; + } + + /** + * Enable error handler: Transform PHP error into `\Hoa\Exception\Error`. + * + * @param bool $enable Enable. + * @return mixed + */ + public static function enableErrorHandler($enable = true) + { + if (false === $enable) { + return restore_error_handler(); + } + + return set_error_handler( + function ($no, $str, $file = null, $line = null, $ctx = null) { + if (0 === ($no & error_reporting())) { + return; + } + + $trace = debug_backtrace(); + array_shift($trace); + array_shift($trace); + + throw new Error($str, $no, $file, $line, $trace); + } + ); + } +} diff --git a/vendor/hoa/exception/Exception.php b/vendor/hoa/exception/Exception.php new file mode 100644 index 0000000000..23f95fbc2d --- /dev/null +++ b/vendor/hoa/exception/Exception.php @@ -0,0 +1,100 @@ +send(); + + return; + } + + /** + * Send the exception on hoa://Event/Exception. + * + * @return void + */ + public function send() + { + Event::notify( + 'hoa://Event/Exception', + $this, + new Event\Bucket($this) + ); + + return; + } +} + +/** + * Flex entity. + */ +Consistency::flexEntity('Hoa\Exception\Exception'); diff --git a/vendor/hoa/exception/Group.php b/vendor/hoa/exception/Group.php new file mode 100644 index 0000000000..e5dee37d13 --- /dev/null +++ b/vendor/hoa/exception/Group.php @@ -0,0 +1,283 @@ +_group = new \SplStack(); + $this->beginTransaction(); + + return; + } + + /** + * Raise an exception as a string. + * + * @param bool $previous Whether raise previous exception if exists. + * @return string + */ + public function raise($previous = false) + { + $out = parent::raise($previous); + + if (0 >= count($this)) { + return $out; + } + + $out .= "\n\n" . 'Contains the following exceptions:'; + + foreach ($this as $exception) { + $out .= + "\n\n" . ' • ' . + str_replace( + "\n", + "\n" . ' ', + $exception->raise($previous) + ); + } + + return $out; + } + + /** + * Begin a transaction. + * + * @return \Hoa\Exception\Group + */ + public function beginTransaction() + { + $this->_group->push(new \ArrayObject()); + + return $this; + } + + /** + * Rollback a transaction. + * + * @return \Hoa\Exception\Group + */ + public function rollbackTransaction() + { + if (1 >= count($this->_group)) { + return $this; + } + + $this->_group->pop(); + + return $this; + } + + /** + * Commit a transaction. + * + * @return \Hoa\Exception\Group + */ + public function commitTransaction() + { + if (false === $this->hasUncommittedExceptions()) { + $this->_group->pop(); + + return $this; + } + + foreach ($this->_group->pop() as $index => $exception) { + $this[$index] = $exception; + } + + return $this; + } + + /** + * Check if there is uncommitted exceptions. + * + * @return bool + */ + public function hasUncommittedExceptions() + { + return + 1 < count($this->_group) && + 0 < count($this->_group->top()); + } + + /** + * Check if an index in the group exists. + * + * @param mixed $index Index. + * @return bool + */ + public function offsetExists($index) + { + foreach ($this->_group as $group) { + if (isset($group[$index])) { + return true; + } + } + + return false; + } + + /** + * Get an exception from the group. + * + * @param mixed $index Index. + * @return Exception + */ + public function offsetGet($index) + { + foreach ($this->_group as $group) { + if (isset($group[$index])) { + return $group[$index]; + } + } + + return null; + } + + /** + * Set an exception in the group. + * + * @param mixed $index Index. + * @param Exception $exception Exception. + * @return void + */ + public function offsetSet($index, $exception) + { + if (!($exception instanceof \Exception)) { + return null; + } + + $group = $this->_group->top(); + + if (null === $index || + true === is_int($index)) { + $group[] = $exception; + } else { + $group[$index] = $exception; + } + + return; + } + + /** + * Remove an exception in the group. + * + * @param mixed $index Index. + * @return void + */ + public function offsetUnset($index) + { + foreach ($this->_group as $group) { + if (isset($group[$index])) { + unset($group[$index]); + } + } + + return; + } + + /** + * Get committed exceptions in the group. + * + * @return \ArrayObject + */ + public function getExceptions() + { + return $this->_group->bottom(); + } + + /** + * Get an iterator over all exceptions (committed or not). + * + * @return \ArrayIterator + */ + public function getIterator() + { + return $this->getExceptions()->getIterator(); + } + + /** + * Count the number of committed exceptions. + * + * @return int + */ + public function count() + { + return count($this->getExceptions()); + } + + /** + * Count the stack size, i.e. the number of opened transactions. + * + * @return int + */ + public function getStackSize() + { + return count($this->_group); + } +} diff --git a/vendor/hoa/exception/Idle.php b/vendor/hoa/exception/Idle.php new file mode 100644 index 0000000000..a94235438c --- /dev/null +++ b/vendor/hoa/exception/Idle.php @@ -0,0 +1,312 @@ +_tmpArguments = $arguments; + parent::__construct($message, $code, $previous); + $this->_rawMessage = $message; + $this->message = @vsprintf($message, $this->getArguments()); + + return; + } + + /** + * Get the backtrace. + * Do not use \Exception::getTrace() any more. + * + * @return array + */ + public function getBacktrace() + { + if (null === $this->_trace) { + $this->_trace = $this->getTrace(); + } + + return $this->_trace; + } + + /** + * Get previous. + * Do not use \Exception::getPrevious() any more. + * + * @return \Exception + */ + public function getPreviousThrow() + { + if (null === $this->_previous) { + $this->_previous = $this->getPrevious(); + } + + return $this->_previous; + } + + /** + * Get arguments for the message. + * + * @return array + */ + public function getArguments() + { + if (null === $this->_arguments) { + $arguments = $this->_tmpArguments; + + if (!is_array($arguments)) { + $arguments = [$arguments]; + } + + foreach ($arguments as &$value) { + if (null === $value) { + $value = '(null)'; + } + } + + $this->_arguments = $arguments; + unset($this->_tmpArguments); + } + + return $this->_arguments; + } + + /** + * Get the raw message. + * + * @return string + */ + public function getRawMessage() + { + return $this->_rawMessage; + } + + /** + * Get the message already formatted. + * + * @return string + */ + public function getFormattedMessage() + { + return $this->getMessage(); + } + + /** + * Get the source of the exception (class, method, function, main etc.). + * + * @return string + */ + public function getFrom() + { + $trace = $this->getBacktrace(); + $from = '{main}'; + + if (!empty($trace)) { + $t = $trace[0]; + $from = ''; + + if (isset($t['class'])) { + $from .= $t['class'] . '::'; + } + + if (isset($t['function'])) { + $from .= $t['function'] . '()'; + } + } + + return $from; + } + + /** + * Raise an exception as a string. + * + * @param bool $previous Whether raise previous exception if exists. + * @return string + */ + public function raise($previous = false) + { + $message = $this->getFormattedMessage(); + $trace = $this->getBacktrace(); + $file = '/dev/null'; + $line = -1; + $pre = $this->getFrom(); + + if (!empty($trace)) { + $file = isset($trace['file']) ? $trace['file'] : null; + $line = isset($trace['line']) ? $trace['line'] : null; + } + + $pre .= ': '; + + try { + $out = + $pre . '(' . $this->getCode() . ') ' . $message . "\n" . + 'in ' . $this->getFile() . ' at line ' . + $this->getLine() . '.'; + } catch (\Exception $e) { + $out = + $pre . '(' . $this->getCode() . ') ' . $message . "\n" . + 'in ' . $file . ' around line ' . $line . '.'; + } + + if (true === $previous && + null !== $previous = $this->getPreviousThrow()) { + $out .= + "\n\n" . ' ⬇' . "\n\n" . + 'Nested exception (' . get_class($previous) . '):' . "\n" . + ($previous instanceof self + ? $previous->raise(true) + : $previous->getMessage()); + } + + return $out; + } + + /** + * Catch uncaught exception (only \Hoa\Exception\Idle and children). + * + * @param \Throwable $exception The exception. + * @return void + * @throws \Throwable + */ + public static function uncaught($exception) + { + if (!($exception instanceof self)) { + throw $exception; + } + + while (0 < ob_get_level()) { + ob_end_flush(); + } + + echo + 'Uncaught exception (' . get_class($exception) . '):' . "\n" . + $exception->raise(true); + + return; + } + + /** + * String representation of object. + * + * @return string + */ + public function __toString() + { + return $this->raise(); + } + + /** + * Enable uncaught exception handler. + * This is restricted to Hoa's exceptions only. + * + * @param bool $enable Enable. + * @return mixed + */ + public static function enableUncaughtHandler($enable = true) + { + if (false === $enable) { + return restore_exception_handler(); + } + + return set_exception_handler(function ($exception) { + return self::uncaught($exception); + }); + } +} diff --git a/vendor/hoa/exception/README.md b/vendor/hoa/exception/README.md new file mode 100644 index 0000000000..67cc9e6ed4 --- /dev/null +++ b/vendor/hoa/exception/README.md @@ -0,0 +1,231 @@ +

+ Hoa +

+ +--- + +

+ Build status + Code coverage + Packagist + License +

+

+ Hoa is a modular, extensible and + structured set of PHP libraries.
+ Moreover, Hoa aims at being a bridge between industrial and research worlds. +

+ +# Hoa\Exception + +[![Help on IRC](https://img.shields.io/badge/help-%23hoaproject-ff0066.svg)](https://webchat.freenode.net/?channels=#hoaproject) +[![Help on Gitter](https://img.shields.io/badge/help-gitter-ff0066.svg)](https://gitter.im/hoaproject/central) +[![Documentation](https://img.shields.io/badge/documentation-hack_book-ff0066.svg)](https://central.hoa-project.net/Documentation/Library/Exception) +[![Board](https://img.shields.io/badge/organisation-board-ff0066.svg)](https://waffle.io/hoaproject/exception) + +This library allows to use advanced exceptions. It provides generic exceptions +(that are sent over the `hoa://Event/Exception` event channel), idle exceptions +(that are not sent over an event channel), uncaught exception handlers, errors +to exceptions handler and group of exceptions (with transactions). + +[Learn more](https://central.hoa-project.net/Documentation/Library/Exception). + +## Installation + +With [Composer](https://getcomposer.org/), to include this library into +your dependencies, you need to +require [`hoa/exception`](https://packagist.org/packages/hoa/exception): + +```sh +$ composer require hoa/exception '~1.0' +``` + +For more installation procedures, please read [the Source +page](https://hoa-project.net/Source.html). + +## Testing + +Before running the test suites, the development dependencies must be installed: + +```sh +$ composer install +``` + +Then, to run all the test suites: + +```sh +$ vendor/bin/hoa test:run +``` + +For more information, please read the [contributor +guide](https://hoa-project.net/Literature/Contributor/Guide.html). + +## Quick usage + +We propose a quick overview of how to use generic exceptions, how to listen all +thrown exceptions through events and how to use group of exceptions. + +### Generic exceptions + +An exception is constitued of: + * A message, + * A code (optional), + * A list of arguments for the message (à la `printf`, optional), + * A previous exception (optional). + +Thus, the following example builds an exception: + +```php +$exception = new Hoa\Exception\Exception('Hello %s!', 0, 'world'); +``` + +The exception message will be: `Hello world!`. The “raise” message (with all +information, not only the message) is: + +``` +{main}: (0) Hello world! +in … at line …. +``` + +Previous exceptions are shown too, for instance: + +```php +$previous = new Hoa\Exception\Exception('Hello previous.'); +$exception = new Hoa\Exception\Exception('Hello %s!', 0, 'world', $previous); + +echo $exception->raise(true); + +/** + * Will output: + * {main}: (0) Hello world! + * in … at line …. + * + * ⬇ + * + * Nested exception (Hoa\Exception\Exception): + * {main}: (0) Hello previous. + * in … at line …. + */ +``` + +### Listen exceptions through events + +Most exceptions in Hoa extend `Hoa\Exception\Exception`, which fire themselves +on the `hoa://Event/Exception` event channel (please, see [the `Hoa\Event` +library](http://central.hoa-project.net/Resource/Library/Event)). Consequently, +we can listen for all exceptions that are thrown in the application by writing: + +```php +Hoa\Event\Event::getEvent('hoa://Event/Exception')->attach( + function (Hoa\Event\Bucket $bucket) { + $exception = $bucket->getData(); + // … + } +); +``` + +Only the `Hoa\Exception\Idle` exceptions are not fired on the channel event. + +### Group and transactions + +Groups of exceptions are represented by the `Hoa\Exception\Group`. A group is an +exception that contains one or many exceptions. A transactional API is provided +to add more exceptions in the group with the following methods: + * `beginTransaction` to start a transaction, + * `rollbackTransaction` to remove all newly added exceptions since + `beginTransaction` call, + * `commitTransaction` to merge all newly added exceptions in the previous + transaction, + * `hasUncommittedExceptions` to check whether they are pending exceptions or + not. + +For instance, if an exceptional behavior is due to several reasons, a group of +exceptions can be thrown instead of one exception. Group can be nested too, +which is useful to represent a tree of exceptions. Thus: + +```php +// A group of exceptions. +$group = new Hoa\Exception\Group('Failed because of several reasons.'); +$group['first'] = new Hoa\Exception\Exception('First reason'); +$group['second'] = new Hoa\Exception\Exception('Second reason'); + +// Can nest another group. +$group['third'] = new Hoa\Exception\Group('Third reason'); +$group['third']['fourth'] = new Hoa\Exception\Exception('Fourth reason'); + +echo $group->raise(true); + +/** + * Will output: + * {main}: (0) Failed because of several reasons. + * in … at line …. + * + * Contains the following exceptions: + * + * • {main}: (0) First reason + * in … at line …. + * + * • {main}: (0) Second reason + * in … at line …. + * + * • {main}: (0) Third reason + * in … at line …. + * + * Contains the following exceptions: + * + * • {main}: (0) Fourth reason + * in … at line …. + */ +``` + +The following example uses a transaction to add new exceptions in the group: + +```php +$group = new Hoa\Exception\Group('Failed because of several reasons.'); +$group[] = new Hoa\Exception\Exception('Always present.'); + +$group->beginTransaction(); + +$group[] = new Hoa\Exception\Exception('Might be present.'); + +if (true === $condition) { + $group->commitTransaction(); +} else { + $group->rollbackTransaction(); +} +``` + +## Documentation + +The +[hack book of `Hoa\Exception`](https://central.hoa-project.net/Documentation/Library/Exception) +contains detailed information about how to use this library and how it works. + +To generate the documentation locally, execute the following commands: + +```sh +$ composer require --dev hoa/devtools +$ vendor/bin/hoa devtools:documentation --open +``` + +More documentation can be found on the project's website: +[hoa-project.net](https://hoa-project.net/). + +## Getting help + +There are mainly two ways to get help: + + * On the [`#hoaproject`](https://webchat.freenode.net/?channels=#hoaproject) + IRC channel, + * On the forum at [users.hoa-project.net](https://users.hoa-project.net). + +## Contribution + +Do you want to contribute? Thanks! A detailed [contributor +guide](https://hoa-project.net/Literature/Contributor/Guide.html) explains +everything you need to know. + +## License + +Hoa is under the New BSD License (BSD-3-Clause). Please, see +[`LICENSE`](https://hoa-project.net/LICENSE) for details. diff --git a/vendor/hoa/exception/Test/Unit/Error.php b/vendor/hoa/exception/Test/Unit/Error.php new file mode 100644 index 0000000000..e4f3702546 --- /dev/null +++ b/vendor/hoa/exception/Test/Unit/Error.php @@ -0,0 +1,145 @@ +when($result = new SUT('foo', 42, '/hoa/flatland', 153)) + ->then + ->object($result) + ->isInstanceOf('Hoa\Exception\Exception'); + } + + public function case_get_message() + { + $this + ->given($exception = new SUT('foo', 42, '/hoa/flatland', 153)) + ->when($result = $exception->raise()) + ->then + ->string($result) + ->isEqualTo( + '{main}: (42) foo' . "\n" . + 'in /hoa/flatland at line 153.' + ); + } + + public function case_disable_error_handler() + { + $this + ->given( + $this->function->restore_error_handler = function () use (&$called) { + $called = true; + + return null; + } + ) + ->when($result = SUT::enableErrorHandler(false)) + ->then + ->variable($result) + ->isNull() + ->boolean($called) + ->isTrue(); + } + + public function case_enable_error_handler() + { + $self = $this; + + $this + ->given( + $this->function->set_error_handler = function ($handler) use ($self, &$called) { + $called = true; + + $self + ->object($handler) + ->isInstanceOf('Closure') + ->let($reflection = new \ReflectionObject($handler)) + ->array($invokeParameters = $reflection->getMethod('__invoke')->getParameters()) + ->hasSize(5) + ->string($invokeParameters[0]->getName()) + ->isEqualTo('no') + ->string($invokeParameters[1]->getName()) + ->isEqualTo('str') + ->string($invokeParameters[2]->getName()) + ->isEqualTo('file') + ->boolean($invokeParameters[2]->isOptional()) + ->isTrue() + ->string($invokeParameters[3]->getName()) + ->isEqualTo('line') + ->boolean($invokeParameters[3]->isOptional()) + ->isTrue() + ->string($invokeParameters[4]->getName()) + ->isEqualTo('ctx') + ->boolean($invokeParameters[4]->isOptional()) + ->isTrue(); + + return null; + } + ) + ->when($result = SUT::enableErrorHandler()) + ->then + ->variable($result) + ->isNull() + ->boolean($called) + ->isTrue(); + } + + public function case_error_handler() + { + $this + ->given(SUT::enableErrorHandler()) + ->exception(function () { + ++$i; + }) + ->isInstanceOf('Hoa\Exception\Error') + ->hasMessage('Undefined variable: i'); + } +} diff --git a/vendor/hoa/exception/Test/Unit/Exception.php b/vendor/hoa/exception/Test/Unit/Exception.php new file mode 100644 index 0000000000..d5cb492c8b --- /dev/null +++ b/vendor/hoa/exception/Test/Unit/Exception.php @@ -0,0 +1,97 @@ +when($result = new SUT('foo')) + ->then + ->object($result) + ->isInstanceOf('Hoa\Exception\Idle'); + } + + public function case_event_is_registered() + { + $this + ->given(new SUT('foo')) + ->when($result = Event::eventExists('hoa://Event/Exception')) + ->then + ->boolean($result) + ->isTrue(); + } + + public function case_event_is_sent() + { + $self = $this; + + $this + ->given( + Event::getEvent('hoa://Event/Exception')->attach( + function (Event\Bucket $bucket) use ($self, &$called) { + $called = true; + + $self + ->object($bucket->getSource()) + ->isInstanceOf('Hoa\Exception\Exception') + ->string($bucket->getSource()->getMessage()) + ->isEqualTo('foo') + ->object($bucket->getData()) + ->isIdenticalTo($bucket->getSource()); + } + ) + ) + ->when(new SUT('foo')) + ->then + ->boolean($called) + ->isTrue(); + } +} diff --git a/vendor/hoa/exception/Test/Unit/Group.php b/vendor/hoa/exception/Test/Unit/Group.php new file mode 100644 index 0000000000..45f371bfbd --- /dev/null +++ b/vendor/hoa/exception/Test/Unit/Group.php @@ -0,0 +1,610 @@ +when($result = new SUT('foo')) + ->then + ->object($result) + ->isInstanceOf('Hoa\Exception\Exception') + ->isInstanceOf('ArrayAccess') + ->isInstanceOf('IteratorAggregate') + ->isInstanceOf('Countable'); + } + + public function case_constructor() + { + $this + ->given( + $message = 'foo %s %d %s', + $code = 7, + $arguments = ['arg', 42, null], + $previous = new SUT('previous') + ) + ->when($result = new SUT($message, $code, $arguments, $previous), $line = __LINE__) + ->then + ->string($result->getMessage()) + ->isEqualTo('foo arg 42 (null)') + ->integer($result->getCode()) + ->isEqualTo(7) + ->array($result->getArguments()) + ->isEqualTo(['arg', 42, '(null)']) + ->object($result->getPreviousThrow()) + ->isIdenticalTo($previous) + ->boolean($result->hasUncommittedExceptions()) + ->isFalse(); + } + + public function case_raise_zero_exception() + { + $this + ->given($group = new SUT('foo'), $line = __LINE__) + ->when($result = $group->raise()) + ->then + ->string($result) + ->isEqualTo( + __METHOD__ . '(): (0) foo' . "\n" . + 'in ' . __FILE__ . ' at line ' . $line . '.' + ); + } + + public function case_raise_one_exception() + { + $this + ->given( + $exception1 = new SUT('bar'), $barLine = __LINE__, + $group = new SUT('foo'), $fooLine = __LINE__, + $group[] = $exception1 + ) + ->when($result = $group->raise()) + ->then + ->string($result) + ->isEqualTo( + __METHOD__ . '(): (0) foo' . "\n" . + 'in ' . __FILE__ . ' at line ' . $fooLine . '.' . "\n\n" . + 'Contains the following exceptions:' . "\n\n" . + ' • ' . __METHOD__ . '(): (0) bar' . "\n" . + ' in ' . __FILE__ . ' at line ' . $barLine . '.' + ); + } + + public function case_raise_more_exceptions() + { + $this + ->given( + $exception1 = new SUT('bar'), $barLine = __LINE__, + $exception2 = new SUT('baz'), $bazLine = __LINE__, + $group = new SUT('foo'), $fooLine = __LINE__, + $group[] = $exception1, + $group[] = $exception2 + ) + ->when($result = $group->raise()) + ->then + ->string($result) + ->isEqualTo( + __METHOD__ . '(): (0) foo' . "\n" . + 'in ' . __FILE__ . ' at line ' . $fooLine . '.' . "\n\n" . + 'Contains the following exceptions:' . "\n\n" . + ' • ' . __METHOD__ . '(): (0) bar' . "\n" . + ' in ' . __FILE__ . ' at line ' . $barLine . '.' . "\n\n" . + ' • ' . __METHOD__ . '(): (0) baz' . "\n" . + ' in ' . __FILE__ . ' at line ' . $bazLine . '.' + ); + } + + public function case_begin_transaction() + { + $this + ->given( + $group = new SUT('foo'), + $oldStackSize = $group->getStackSize() + ) + ->when( + $result = $group->beginTransaction(), + $stackSize = $group->getStackSize() + ) + ->then + ->integer($oldStackSize) + ->isEqualTo(1) + ->object($result) + ->isIdenticalTo($group) + ->integer($stackSize) + ->isEqualTo($oldStackSize + 1); + } + + public function case_rollback_transaction_with_an_empty_stack() + { + $this + ->given( + $group = new SUT('foo'), + $oldStackSize = $group->getStackSize() + ) + ->when( + $result = $group->rollbackTransaction(), + $stackSize = $group->getStackSize() + ) + ->then + ->integer($oldStackSize) + ->isEqualTo(1) + ->object($result) + ->isIdenticalTo($group) + ->integer($stackSize) + ->isEqualTo($oldStackSize); + } + + public function case_rollback_transaction() + { + $this + ->given( + $group = new SUT('foo'), + $group->beginTransaction(), + $group->beginTransaction(), + $oldStackSize = $group->getStackSize(), + $group->rollbackTransaction() + ) + ->when( + $result = $group->rollbackTransaction(), + $stackSize = $group->getStackSize() + ) + ->then + ->integer($oldStackSize) + ->isEqualTo(3) + ->object($result) + ->isIdenticalTo($group) + ->integer($stackSize) + ->isEqualTo($oldStackSize - 2); + } + + public function case_commit_transaction_with_an_empty_stack() + { + $this + ->given( + $group = new SUT('foo'), + $group->beginTransaction(), + $oldCount = count($group), + $oldStackSize = $group->getStackSize() + ) + ->when( + $result = $group->commitTransaction(), + $count = count($group), + $stackSize = $group->getStackSize() + ) + ->then + ->integer($oldCount) + ->isEqualTo(0) + ->integer($oldStackSize) + ->isEqualTo(2) + ->object($result) + ->isIdenticalTo($group) + ->integer($count) + ->isEqualTo($oldCount) + ->integer($stackSize) + ->isEqualTo($oldStackSize - 1); + } + + public function case_commit_transaction() + { + $this + ->given( + $group = new SUT('foo'), + $group->beginTransaction(), + $exception1 = new SUT('bar'), + $exception2 = new SUT('baz'), + $group[] = $exception1, + $group[] = $exception2, + $oldCount = count($group), + $oldStackSize = $group->getStackSize() + ) + ->when( + $result = $group->commitTransaction(), + $count = count($group), + $stackSize = $group->getStackSize() + ) + ->then + ->integer($oldCount) + ->isEqualTo(0) + ->integer($oldStackSize) + ->isEqualTo(2) + ->object($result) + ->isIdenticalTo($group) + ->integer($count) + ->isEqualTo($oldCount + 2) + ->integer($stackSize) + ->isEqualTo($oldStackSize - 1) + ->array(iterator_to_array($group->getIterator())) + ->isEqualTo([ + 0 => $exception1, + 1 => $exception2 + ]); + } + + public function case_has_uncommitted_exceptions() + { + $this + ->given( + $group = new SUT('foo'), + $group->beginTransaction(), + $group[] = new SUT('bar') + ) + ->when($result = $group->hasUncommittedExceptions()) + ->then + ->boolean($result) + ->isTrue(); + } + + public function case_has_no_uncommitted_exceptions() + { + $this + ->given( + $group = new SUT('foo'), + $group->beginTransaction() + ) + ->when($result = $group->hasUncommittedExceptions()) + ->then + ->boolean($result) + ->isFalse(); + } + + public function case_has_no_uncommitted_exceptions_with_empty_stack() + { + $this + ->given( + $group = new SUT('foo'), + $group[] = new SUT('bar') + ) + ->when($result = $group->hasUncommittedExceptions()) + ->then + ->boolean($result) + ->isFalse(); + } + + public function case_offset_exists_with_no_uncommited_exceptions() + { + $this + ->given( + $group = new SUT('foo'), + $group['bar'] = new SUT('bar') + ) + ->when($result = $group->offsetExists('bar')) + ->then + ->boolean($result) + ->isTrue(); + } + + public function case_offset_does_not_exist_with_no_uncommited_exceptions() + { + $this + ->given( + $group = new SUT('foo'), + $group['bar'] = new SUT('bar') + ) + ->when($result = $group->offsetExists('baz')) + ->then + ->boolean($result) + ->isFalse(); + } + + public function case_offset_exists() + { + $this + ->given( + $group = new SUT('foo'), + $group->beginTransaction(), + $group->beginTransaction(), + $group['bar'] = new SUT('bar') + ) + ->when($result = $group->offsetExists('bar')) + ->then + ->boolean($result) + ->isTrue(); + } + + public function case_offset_does_not_exist() + { + $this + ->given( + $group = new SUT('foo'), + $group->beginTransaction(), + $group->beginTransaction(), + $group['bar'] = new SUT('bar') + ) + ->when($result = $group->offsetExists('baz')) + ->then + ->boolean($result) + ->isFalse(); + } + + public function case_offset_get_with_no_uncommited_exceptions() + { + $this + ->given( + $group = new SUT('foo'), + $exception1 = new SUT('bar'), + $group['bar'] = $exception1 + ) + ->when($result = $group->offsetGet('bar')) + ->then + ->object($result) + ->isIdenticalTo($exception1); + } + + public function case_offset_get_does_not_exist_with_no_uncommited_exceptions() + { + $this + ->given( + $group = new SUT('foo'), + $exception1 = new SUT('bar'), + $group['bar'] = $exception1 + ) + ->when($result = $group->offsetGet('baz')) + ->then + ->variable($result) + ->isNull(); + } + + public function case_offset_get() + { + $this + ->given( + $group = new SUT('foo'), + $group->beginTransaction(), + $group->beginTransaction(), + $exception1 = new SUT('bar'), + $group['bar'] = $exception1 + ) + ->when($result = $group->offsetGet('bar')) + ->then + ->object($result) + ->isIdenticalTo($exception1); + } + + public function case_offset_get_does_not_exist() + { + $this + ->given( + $group = new SUT('foo'), + $group->beginTransaction(), + $group->beginTransaction(), + $exception1 = new SUT('bar'), + $group['bar'] = $exception1 + ) + ->when($result = $group->offsetGet('baz')) + ->then + ->variable($result) + ->isNull(); + } + + public function case_offset_set_not_an_exception() + { + $this + ->given($group = new SUT('foo')) + ->when($group->offsetSet('bar', new \StdClass())) + ->then + ->boolean($group->offsetExists('bar')) + ->isFalse(); + } + + public function case_offset_set() + { + $this + ->given( + $group = new SUT('foo'), + $exception1 = new SUT('bar') + ) + ->when($result = $group->offsetExists('bar')) + ->then + ->boolean($result) + ->isFalse() + + ->when($group->offsetSet('bar', $exception1)) + ->then + ->boolean($group->offsetExists('bar')) + ->isTrue() + ->object($group->offsetGet('bar')) + ->isIdenticalTo($exception1); + } + + public function case_offset_set_with_a_null_index() + { + $this + ->given( + $group = new SUT('foo'), + $exception1 = new SUT('bar') + ) + ->when($group->offsetSet(null, $exception1)) + ->then + ->boolean($group->offsetExists(0)) + ->isTrue() + ->object($group->offsetGet(0)) + ->isIdenticalTo($exception1); + } + + public function case_offset_set_with_an_integer_index() + { + $this + ->given( + $group = new SUT('foo'), + $exception1 = new SUT('bar') + ) + ->when($group->offsetSet(42, $exception1)) + ->then + ->boolean($group->offsetExists(42)) + ->isFalse() + ->boolean($group->offsetExists(0)) + ->isTrue() + ->object($group->offsetGet(0)) + ->isIdenticalTo($exception1); + } + + public function case_offset_unset_with_no_uncommited_exceptions() + { + $this + ->given( + $group = new SUT('foo'), + $group['bar'] = new SUT('bar') + ) + ->when($group->offsetUnset('bar')) + ->then + ->boolean($group->offsetExists('bar')) + ->isFalse(); + } + + public function case_offset_unset_does_not_exist_with_no_uncommited_exceptions() + { + $this + ->given($group = new SUT('foo')) + ->when($group->offsetUnset('bar')) + ->then + ->boolean($group->offsetExists('bar')) + ->isFalse(); + } + + public function case_offset_unset() + { + $this + ->given( + $group = new SUT('foo'), + $group->beginTransaction(), + $group->beginTransaction(), + $group['bar'] = new SUT('bar') + ) + ->when($result = $group->offsetUnset('bar')) + ->then + ->boolean($group->offsetExists('bar')) + ->isFalse(); + } + + public function case_offset_unset_does_not_exist() + { + $this + ->given( + $group = new SUT('foo'), + $group->beginTransaction(), + $group->beginTransaction() + ) + ->when($result = $group->offsetUnset('bar')) + ->then + ->boolean($group->offsetExists('bar')) + ->isFalse(); + } + + public function case_get_exceptions() + { + $this + ->given( + $group = new SUT('foo'), + $exception1 = new SUT('bar'), + $exception2 = new SUT('baz'), + $group['bar'] = $exception1, + $group->beginTransaction(), + $group['baz'] = $exception2 + ) + ->when($result = $group->getExceptions()) + ->then + ->object($result) + ->isInstanceOf('ArrayObject') + ->object($result['bar']) + ->isIdenticalTo($exception1); + } + + public function case_get_iterator() + { + $this + ->given( + $group = new SUT('foo'), + $exception1 = new SUT('bar'), + $group['bar'] = $exception1 + ) + ->when($result = $group->getIterator()) + ->then + ->object($result) + ->isInstanceOf('ArrayIterator') + ->array(iterator_to_array($result)) + ->isEqualTo([ + 'bar' => $exception1 + ]); + } + + public function case_count() + { + $this + ->given( + $group = new SUT('foo'), + $exception1 = new SUT('bar'), + $exception2 = new SUT('baz'), + $group['bar'] = $exception1, + $group->beginTransaction(), + $group['baz'] = $exception2 + ) + ->when($result = count($group)) + ->then + ->integer($result) + ->isEqualTo(1); + } + + public function get_get_stack_size() + { + $this + ->given( + $group = new SUT('foo'), + $exception1 = new SUT('bar'), + $exception2 = new SUT('baz'), + $group['bar'] = $exception1, + $group->beginTransaction(), + $group['baz'] = $exception2 + ) + ->when($result = $group->getStackSize()) + ->then + ->integer($result) + ->isEqualTo(2); + } +} diff --git a/vendor/hoa/exception/Test/Unit/Idle.php b/vendor/hoa/exception/Test/Unit/Idle.php new file mode 100644 index 0000000000..df1f46ffee --- /dev/null +++ b/vendor/hoa/exception/Test/Unit/Idle.php @@ -0,0 +1,267 @@ +when($result = new SUT('foo')) + ->then + ->object($result) + ->isInstanceOf('Exception'); + } + + public function case_get_backtrace() + { + $this + ->given($exception = new SUT('foo')) + ->when($result = $exception->getBacktrace()) + ->then + ->array($result) + ->hasKey(0) + ->array($result[0]) + ->hasKey('file') + ->hasKey('line') + ->hasKey('function') + ->hasKey('class') + ->hasKey('type') + ->hasKey('args'); + } + + public function case_get_previous_throw() + { + $this + ->given( + $previous = new SUT('previous'), + $exception = new SUT('foo', 0, [], $previous) + ) + ->when($result = $exception->getPreviousThrow()) + ->then + ->object($result) + ->isIdenticalTo($previous); + } + + public function case_get_arguments() + { + $this + ->given($exception = new SUT('foo', 0, ['arg', 42, null])) + ->when($result = $exception->getArguments()) + ->then + ->array($result) + ->isEqualTo(['arg', 42, '(null)']); + } + + public function case_get_arguments_from_a_string() + { + $this + ->given($exception = new SUT('foo', 0, 'arg')) + ->when($result = $exception->getArguments()) + ->then + ->array($result) + ->isEqualTo(['arg']); + } + + public function case_get_raw_message() + { + $this + ->given( + $message = 'foo %s', + $exception = new SUT($message) + ) + ->when($result = $exception->getRawMessage()) + ->then + ->string($result) + ->isEqualTo($message); + } + + public function case_get_formatted_message() + { + $this + ->given( + $message = 'foo %s', + $exception = new SUT($message, 0, 'bar') + ) + ->when($result = $exception->getFormattedMessage()) + ->then + ->string($result) + ->isEqualTo($exception->getMessage()) + ->isEqualTo('foo bar'); + } + + public function case_get_from_object() + { + $this + ->given($exception = new SUT('foo')) + ->when($result = $exception->getFrom()) + ->then + ->string($result) + ->isEqualTo(__METHOD__ . '()'); + } + + public function case_raise() + { + $this + ->given($exception = new SUT('foo'), $line = __LINE__) + ->when($result = $exception->raise()) + ->then + ->string($result) + ->isEqualTo( + __METHOD__ . '(): (0) foo' . "\n" . + 'in ' . __FILE__ . ' at line ' . $line . '.' + ); + } + + public function case_raise_with_previous() + { + $this + ->given( + $previous = new SUT('previous'), $previousLine = __LINE__, + $exception = new SUT('foo', 0, [], $previous), $line = __LINE__ + ) + ->when($result = $exception->raise(true)) + ->then + ->string($result) + ->isEqualTo( + __METHOD__ . '(): (0) foo' . "\n" . + 'in ' . __FILE__ . ' at line ' . $line . '.' . "\n\n" . + ' ⬇' . "\n\n" . + 'Nested exception (' . get_class($previous) . '):' . "\n" . + __METHOD__ . '(): (0) previous' . "\n" . + 'in ' . __FILE__ . ' at line ' . $previousLine . '.' + ); + } + + public function case_uncaught() + { + $this + ->given( + $this->function->ob_get_level = 0, + $exception = new SUT('foo'), $line = __LINE__ + ) + ->when($result = SUT::uncaught($exception)) + ->then + ->variable($result) + ->isNull() + ->output + ->isEqualTo( + 'Uncaught exception (' . get_class($exception) . '):' . "\n" . + __METHOD__ . '(): (0) foo' . "\n" . + 'in ' . __FILE__ . ' at line ' . $line . '.' + ); + } + + public function case_uncaught_not_Hoa() + { + $this + ->exception(function () { + SUT::uncaught(new \Exception('foo')); + }) + ->isInstanceOf('Exception') + ->output + ->isEmpty(); + } + + public function case_to_string() + { + $this + ->given($exception = new SUT('foo')) + ->when($result = $exception->__toString()) + ->then + ->string($result) + ->isEqualTo($exception->raise()); + } + + public function case_disable_uncaught_handler() + { + $this + ->given( + $this->function->restore_exception_handler = function () use (&$called) { + $called = true; + + return null; + } + ) + ->when($result = SUT::enableUncaughtHandler(false)) + ->then + ->variable($result) + ->isNull() + ->boolean($called) + ->isTrue(); + } + + public function case_enable_uncaught_handler() + { + $self = $this; + + $this + ->given( + $this->function->set_exception_handler = function ($handler) use ($self, &$called) { + $called = true; + + $self + ->object($handler) + ->isInstanceOf('Closure') + ->let($reflection = new \ReflectionObject($handler)) + ->array($invokeParameters = $reflection->getMethod('__invoke')->getParameters()) + ->hasSize(1) + ->string($invokeParameters[0]->getName()) + ->isEqualTo('exception'); + + return null; + } + ) + ->when($result = SUT::enableUncaughtHandler()) + ->then + ->variable($result) + ->isNull() + ->boolean($called) + ->isTrue(); + } +} diff --git a/vendor/hoa/exception/composer.json b/vendor/hoa/exception/composer.json new file mode 100644 index 0000000000..0751d842c4 --- /dev/null +++ b/vendor/hoa/exception/composer.json @@ -0,0 +1,42 @@ +{ + "name" : "hoa/exception", + "description": "The Hoa\\Exception library.", + "type" : "library", + "keywords" : ["library", "exception"], + "homepage" : "https://hoa-project.net/", + "license" : "BSD-3-Clause", + "authors" : [ + { + "name" : "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name" : "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "support": { + "email" : "support@hoa-project.net", + "irc" : "irc://chat.freenode.net/hoaproject", + "forum" : "https://users.hoa-project.net/", + "docs" : "https://central.hoa-project.net/Documentation/Library/Exception", + "source": "https://central.hoa-project.net/Resource/Library/Exception" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/event" : "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "autoload": { + "psr-4": { + "Hoa\\Exception\\": "." + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + } +} diff --git a/vendor/paragonie/random_compat/LICENSE b/vendor/paragonie/random_compat/LICENSE new file mode 100644 index 0000000000..45c7017dfb --- /dev/null +++ b/vendor/paragonie/random_compat/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Paragon Initiative Enterprises + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/vendor/paragonie/random_compat/composer.json b/vendor/paragonie/random_compat/composer.json new file mode 100644 index 0000000000..34f1381d57 --- /dev/null +++ b/vendor/paragonie/random_compat/composer.json @@ -0,0 +1,38 @@ +{ + "name": "paragonie/random_compat", + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "random", + "polyfill", + "pseudorandom" + ], + "license": "MIT", + "type": "library", + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "support": { + "issues": "https://github.com/paragonie/random_compat/issues", + "email": "info@paragonie.com", + "source": "https://github.com/paragonie/random_compat" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "autoload": { + "files": [ + "lib/random.php" + ] + } +} diff --git a/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey b/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey new file mode 100644 index 0000000000..eb50ebfcd6 --- /dev/null +++ b/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey @@ -0,0 +1,5 @@ +-----BEGIN PUBLIC KEY----- +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEEd+wCqJDrx5B4OldM0dQE0ZMX+lx1ZWm +pui0SUqD4G29L3NGsz9UhJ/0HjBdbnkhIK5xviT0X5vtjacF6ajgcCArbTB+ds+p ++h7Q084NuSuIpNb6YPfoUFgC/CL9kAoc +-----END PUBLIC KEY----- diff --git a/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey.asc b/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey.asc new file mode 100644 index 0000000000..6a1d7f3006 --- /dev/null +++ b/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey.asc @@ -0,0 +1,11 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.0.22 (MingW32) + +iQEcBAABAgAGBQJWtW1hAAoJEGuXocKCZATaJf0H+wbZGgskK1dcRTsuVJl9IWip +QwGw/qIKI280SD6/ckoUMxKDCJiFuPR14zmqnS36k7N5UNPnpdTJTS8T11jttSpg +1LCmgpbEIpgaTah+cELDqFCav99fS+bEiAL5lWDAHBTE/XPjGVCqeehyPYref4IW +NDBIEsvnHPHPLsn6X5jq4+Yj5oUixgxaMPiR+bcO4Sh+RzOVB6i2D0upWfRXBFXA +NNnsg9/zjvoC7ZW73y9uSH+dPJTt/Vgfeiv52/v41XliyzbUyLalf02GNPY+9goV +JHG1ulEEBJOCiUD9cE1PUIJwHA/HqyhHIvV350YoEFiHl8iSwm7SiZu5kPjaq74= +=B6+8 +-----END PGP SIGNATURE----- diff --git a/vendor/paragonie/random_compat/lib/byte_safe_strings.php b/vendor/paragonie/random_compat/lib/byte_safe_strings.php new file mode 100644 index 0000000000..ef24488f9e --- /dev/null +++ b/vendor/paragonie/random_compat/lib/byte_safe_strings.php @@ -0,0 +1,195 @@ + RandomCompat_strlen($binary_string)) { + return ''; + } + + return (string) mb_substr( + (string) $binary_string, + (int) $start, + (int) $length, + '8bit' + ); + } + + } else { + + /** + * substr() implementation that isn't brittle to mbstring.func_overload + * + * This version just uses the default substr() + * + * @param string $binary_string + * @param int $start + * @param int|null $length (optional) + * + * @throws TypeError + * + * @return string + */ + function RandomCompat_substr($binary_string, $start, $length = null) + { + if (!is_string($binary_string)) { + throw new TypeError( + 'RandomCompat_substr(): First argument should be a string' + ); + } + + if (!is_int($start)) { + throw new TypeError( + 'RandomCompat_substr(): Second argument should be an integer' + ); + } + + if ($length !== null) { + if (!is_int($length)) { + throw new TypeError( + 'RandomCompat_substr(): Third argument should be an integer, or omitted' + ); + } + + return (string) substr( + (string )$binary_string, + (int) $start, + (int) $length + ); + } + + return (string) substr( + (string) $binary_string, + (int) $start + ); + } + } +} diff --git a/vendor/paragonie/random_compat/lib/cast_to_int.php b/vendor/paragonie/random_compat/lib/cast_to_int.php new file mode 100644 index 0000000000..1b1bbfe8de --- /dev/null +++ b/vendor/paragonie/random_compat/lib/cast_to_int.php @@ -0,0 +1,77 @@ + operators might accidentally let a float + * through. + * + * @param int|float $number The number we want to convert to an int + * @param bool $fail_open Set to true to not throw an exception + * + * @return float|int + * @psalm-suppress InvalidReturnType + * + * @throws TypeError + */ + function RandomCompat_intval($number, $fail_open = false) + { + if (is_int($number) || is_float($number)) { + $number += 0; + } elseif (is_numeric($number)) { + /** @psalm-suppress InvalidOperand */ + $number += 0; + } + /** @var int|float $number */ + + if ( + is_float($number) + && + $number > ~PHP_INT_MAX + && + $number < PHP_INT_MAX + ) { + $number = (int) $number; + } + + if (is_int($number)) { + return (int) $number; + } elseif (!$fail_open) { + throw new TypeError( + 'Expected an integer.' + ); + } + return $number; + } +} diff --git a/vendor/paragonie/random_compat/lib/error_polyfill.php b/vendor/paragonie/random_compat/lib/error_polyfill.php new file mode 100644 index 0000000000..c02c5c8b4c --- /dev/null +++ b/vendor/paragonie/random_compat/lib/error_polyfill.php @@ -0,0 +1,49 @@ += 70000) { + return; +} + +if (!defined('RANDOM_COMPAT_READ_BUFFER')) { + define('RANDOM_COMPAT_READ_BUFFER', 8); +} + +$RandomCompatDIR = dirname(__FILE__); + +require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'byte_safe_strings.php'; +require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'cast_to_int.php'; +require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'error_polyfill.php'; + +if (!is_callable('random_bytes')) { + /** + * PHP 5.2.0 - 5.6.x way to implement random_bytes() + * + * We use conditional statements here to define the function in accordance + * to the operating environment. It's a micro-optimization. + * + * In order of preference: + * 1. Use libsodium if available. + * 2. fread() /dev/urandom if available (never on Windows) + * 3. mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM) + * 4. COM('CAPICOM.Utilities.1')->GetRandom() + * + * See RATIONALE.md for our reasoning behind this particular order + */ + if (extension_loaded('libsodium')) { + // See random_bytes_libsodium.php + if (PHP_VERSION_ID >= 50300 && is_callable('\\Sodium\\randombytes_buf')) { + require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_libsodium.php'; + } elseif (method_exists('Sodium', 'randombytes_buf')) { + require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_libsodium_legacy.php'; + } + } + + /** + * Reading directly from /dev/urandom: + */ + if (DIRECTORY_SEPARATOR === '/') { + // DIRECTORY_SEPARATOR === '/' on Unix-like OSes -- this is a fast + // way to exclude Windows. + $RandomCompatUrandom = true; + $RandomCompat_basedir = ini_get('open_basedir'); + + if (!empty($RandomCompat_basedir)) { + $RandomCompat_open_basedir = explode( + PATH_SEPARATOR, + strtolower($RandomCompat_basedir) + ); + $RandomCompatUrandom = (array() !== array_intersect( + array('/dev', '/dev/', '/dev/urandom'), + $RandomCompat_open_basedir + )); + $RandomCompat_open_basedir = null; + } + + if ( + !is_callable('random_bytes') + && + $RandomCompatUrandom + && + @is_readable('/dev/urandom') + ) { + // Error suppression on is_readable() in case of an open_basedir + // or safe_mode failure. All we care about is whether or not we + // can read it at this point. If the PHP environment is going to + // panic over trying to see if the file can be read in the first + // place, that is not helpful to us here. + + // See random_bytes_dev_urandom.php + require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_dev_urandom.php'; + } + // Unset variables after use + $RandomCompat_basedir = null; + } else { + $RandomCompatUrandom = false; + } + + /** + * mcrypt_create_iv() + * + * We only want to use mcypt_create_iv() if: + * + * - random_bytes() hasn't already been defined + * - the mcrypt extensions is loaded + * - One of these two conditions is true: + * - We're on Windows (DIRECTORY_SEPARATOR !== '/') + * - We're not on Windows and /dev/urandom is readabale + * (i.e. we're not in a chroot jail) + * - Special case: + * - If we're not on Windows, but the PHP version is between + * 5.6.10 and 5.6.12, we don't want to use mcrypt. It will + * hang indefinitely. This is bad. + * - If we're on Windows, we want to use PHP >= 5.3.7 or else + * we get insufficient entropy errors. + */ + if ( + !is_callable('random_bytes') + && + // Windows on PHP < 5.3.7 is broken, but non-Windows is not known to be. + (DIRECTORY_SEPARATOR === '/' || PHP_VERSION_ID >= 50307) + && + // Prevent this code from hanging indefinitely on non-Windows; + // see https://bugs.php.net/bug.php?id=69833 + ( + DIRECTORY_SEPARATOR !== '/' || + (PHP_VERSION_ID <= 50609 || PHP_VERSION_ID >= 50613) + ) + && + extension_loaded('mcrypt') + ) { + // See random_bytes_mcrypt.php + require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_mcrypt.php'; + } + $RandomCompatUrandom = null; + + /** + * This is a Windows-specific fallback, for when the mcrypt extension + * isn't loaded. + */ + if ( + !is_callable('random_bytes') + && + extension_loaded('com_dotnet') + && + class_exists('COM') + ) { + $RandomCompat_disabled_classes = preg_split( + '#\s*,\s*#', + strtolower(ini_get('disable_classes')) + ); + + if (!in_array('com', $RandomCompat_disabled_classes)) { + try { + $RandomCompatCOMtest = new COM('CAPICOM.Utilities.1'); + if (method_exists($RandomCompatCOMtest, 'GetRandom')) { + // See random_bytes_com_dotnet.php + require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_com_dotnet.php'; + } + } catch (com_exception $e) { + // Don't try to use it. + } + } + $RandomCompat_disabled_classes = null; + $RandomCompatCOMtest = null; + } + + /** + * throw new Exception + */ + if (!is_callable('random_bytes')) { + /** + * We don't have any more options, so let's throw an exception right now + * and hope the developer won't let it fail silently. + * + * @param mixed $length + * @psalm-suppress InvalidReturnType + * @throws Exception + * @return string + */ + function random_bytes($length) + { + unset($length); // Suppress "variable not used" warnings. + throw new Exception( + 'There is no suitable CSPRNG installed on your system' + ); + return ''; + } + } +} + +if (!is_callable('random_int')) { + require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_int.php'; +} + +$RandomCompatDIR = null; diff --git a/vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php b/vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php new file mode 100644 index 0000000000..537d02b27a --- /dev/null +++ b/vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php @@ -0,0 +1,91 @@ +GetRandom($bytes, 0)); + if (RandomCompat_strlen($buf) >= $bytes) { + /** + * Return our random entropy buffer here: + */ + return (string) RandomCompat_substr($buf, 0, $bytes); + } + ++$execCount; + } while ($execCount < $bytes); + + /** + * If we reach here, PHP has failed us. + */ + throw new Exception( + 'Could not gather sufficient random data' + ); + } +} diff --git a/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php b/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php new file mode 100644 index 0000000000..c4e31ccbbb --- /dev/null +++ b/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php @@ -0,0 +1,190 @@ + $st */ + $st = fstat($fp); + if (($st['mode'] & 0170000) !== 020000) { + fclose($fp); + $fp = false; + } + } + } + + if (is_resource($fp)) { + /** + * stream_set_read_buffer() does not exist in HHVM + * + * If we don't set the stream's read buffer to 0, PHP will + * internally buffer 8192 bytes, which can waste entropy + * + * stream_set_read_buffer returns 0 on success + */ + if (is_callable('stream_set_read_buffer')) { + stream_set_read_buffer($fp, RANDOM_COMPAT_READ_BUFFER); + } + if (is_callable('stream_set_chunk_size')) { + stream_set_chunk_size($fp, RANDOM_COMPAT_READ_BUFFER); + } + } + } + + try { + /** @var int $bytes */ + $bytes = RandomCompat_intval($bytes); + } catch (TypeError $ex) { + throw new TypeError( + 'random_bytes(): $bytes must be an integer' + ); + } + + if ($bytes < 1) { + throw new Error( + 'Length must be greater than 0' + ); + } + + /** + * This if() block only runs if we managed to open a file handle + * + * It does not belong in an else {} block, because the above + * if (empty($fp)) line is logic that should only be run once per + * page load. + */ + if (is_resource($fp)) { + /** + * @var int + */ + $remaining = $bytes; + + /** + * @var string|bool + */ + $buf = ''; + + /** + * We use fread() in a loop to protect against partial reads + */ + do { + /** + * @var string|bool + */ + $read = fread($fp, $remaining); + if (!is_string($read)) { + /** + * We cannot safely read from the file. Exit the + * do-while loop and trigger the exception condition + * + * @var string|bool + */ + $buf = false; + break; + } + /** + * Decrease the number of bytes returned from remaining + */ + $remaining -= RandomCompat_strlen($read); + /** + * @var string $buf + */ + $buf .= $read; + } while ($remaining > 0); + + /** + * Is our result valid? + * @var string|bool $buf + */ + if (is_string($buf)) { + if (RandomCompat_strlen($buf) === $bytes) { + /** + * Return our random entropy buffer here: + */ + return $buf; + } + } + } + + /** + * If we reach here, PHP has failed us. + */ + throw new Exception( + 'Error reading from source device' + ); + } +} diff --git a/vendor/paragonie/random_compat/lib/random_bytes_libsodium.php b/vendor/paragonie/random_compat/lib/random_bytes_libsodium.php new file mode 100644 index 0000000000..2e56290182 --- /dev/null +++ b/vendor/paragonie/random_compat/lib/random_bytes_libsodium.php @@ -0,0 +1,91 @@ + 2147483647) { + $buf = ''; + for ($i = 0; $i < $bytes; $i += 1073741824) { + $n = ($bytes - $i) > 1073741824 + ? 1073741824 + : $bytes - $i; + $buf .= \Sodium\randombytes_buf($n); + } + } else { + /** @var string|bool $buf */ + $buf = \Sodium\randombytes_buf($bytes); + } + + if (is_string($buf)) { + if (RandomCompat_strlen($buf) === $bytes) { + return $buf; + } + } + + /** + * If we reach here, PHP has failed us. + */ + throw new Exception( + 'Could not gather sufficient random data' + ); + } +} diff --git a/vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php b/vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php new file mode 100644 index 0000000000..f78b2199a2 --- /dev/null +++ b/vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php @@ -0,0 +1,93 @@ + 2147483647) { + for ($i = 0; $i < $bytes; $i += 1073741824) { + $n = ($bytes - $i) > 1073741824 + ? 1073741824 + : $bytes - $i; + $buf .= Sodium::randombytes_buf((int) $n); + } + } else { + $buf .= Sodium::randombytes_buf((int) $bytes); + } + + if (is_string($buf)) { + if (RandomCompat_strlen($buf) === $bytes) { + return $buf; + } + } + + /** + * If we reach here, PHP has failed us. + */ + throw new Exception( + 'Could not gather sufficient random data' + ); + } +} diff --git a/vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php b/vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php new file mode 100644 index 0000000000..0b13fa73c5 --- /dev/null +++ b/vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php @@ -0,0 +1,79 @@ + operators might accidentally let a float + * through. + */ + + try { + /** @var int $min */ + $min = RandomCompat_intval($min); + } catch (TypeError $ex) { + throw new TypeError( + 'random_int(): $min must be an integer' + ); + } + + try { + /** @var int $max */ + $max = RandomCompat_intval($max); + } catch (TypeError $ex) { + throw new TypeError( + 'random_int(): $max must be an integer' + ); + } + + /** + * Now that we've verified our weak typing system has given us an integer, + * let's validate the logic then we can move forward with generating random + * integers along a given range. + */ + if ($min > $max) { + throw new Error( + 'Minimum value must be less than or equal to the maximum value' + ); + } + + if ($max === $min) { + return (int) $min; + } + + /** + * Initialize variables to 0 + * + * We want to store: + * $bytes => the number of random bytes we need + * $mask => an integer bitmask (for use with the &) operator + * so we can minimize the number of discards + */ + $attempts = $bits = $bytes = $mask = $valueShift = 0; + /** @var int $attempts */ + /** @var int $bits */ + /** @var int $bytes */ + /** @var int $mask */ + /** @var int $valueShift */ + + /** + * At this point, $range is a positive number greater than 0. It might + * overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to + * a float and we will lose some precision. + * + * @var int|float $range + */ + $range = $max - $min; + + /** + * Test for integer overflow: + */ + if (!is_int($range)) { + + /** + * Still safely calculate wider ranges. + * Provided by @CodesInChaos, @oittaa + * + * @ref https://gist.github.com/CodesInChaos/03f9ea0b58e8b2b8d435 + * + * We use ~0 as a mask in this case because it generates all 1s + * + * @ref https://eval.in/400356 (32-bit) + * @ref http://3v4l.org/XX9r5 (64-bit) + */ + $bytes = PHP_INT_SIZE; + /** @var int $mask */ + $mask = ~0; + + } else { + + /** + * $bits is effectively ceil(log($range, 2)) without dealing with + * type juggling + */ + while ($range > 0) { + if ($bits % 8 === 0) { + ++$bytes; + } + ++$bits; + $range >>= 1; + /** @var int $mask */ + $mask = $mask << 1 | 1; + } + $valueShift = $min; + } + + /** @var int $val */ + $val = 0; + /** + * Now that we have our parameters set up, let's begin generating + * random integers until one falls between $min and $max + */ + /** @psalm-suppress RedundantCondition */ + do { + /** + * The rejection probability is at most 0.5, so this corresponds + * to a failure probability of 2^-128 for a working RNG + */ + if ($attempts > 128) { + throw new Exception( + 'random_int: RNG is broken - too many rejections' + ); + } + + /** + * Let's grab the necessary number of random bytes + */ + $randomByteString = random_bytes($bytes); + + /** + * Let's turn $randomByteString into an integer + * + * This uses bitwise operators (<< and |) to build an integer + * out of the values extracted from ord() + * + * Example: [9F] | [6D] | [32] | [0C] => + * 159 + 27904 + 3276800 + 201326592 => + * 204631455 + */ + $val &= 0; + for ($i = 0; $i < $bytes; ++$i) { + $val |= ord($randomByteString[$i]) << ($i * 8); + } + /** @var int $val */ + + /** + * Apply mask + */ + $val &= $mask; + $val += $valueShift; + + ++$attempts; + /** + * If $val overflows to a floating point number, + * ... or is larger than $max, + * ... or smaller than $min, + * then try again. + */ + } while (!is_int($val) || $val > $max || $val < $min); + + return (int) $val; + } +} diff --git a/vendor/phpseclib/phpseclib/composer.lock b/vendor/phpseclib/phpseclib/composer.lock new file mode 100644 index 0000000000..f50ebed213 --- /dev/null +++ b/vendor/phpseclib/phpseclib/composer.lock @@ -0,0 +1,1783 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "422b05a6ce122760976256ff21e9381b", + "content-hash": "3bd75e9c1741d7c0c0930855e5b96abb", + "packages": [ + { + "name": "paragonie/constant_time_encoding", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/constant_time_encoding.git", + "reference": "fdb1e311153233315e0f7699711e3845d81ed00f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/fdb1e311153233315e0f7699711e3845d81ed00f", + "reference": "fdb1e311153233315e0f7699711e3845d81ed00f", + "shasum": "" + }, + "require": { + "php": "^5.3|^7" + }, + "require-dev": { + "paragonie/random_compat": "^1.4|^2.0", + "phpunit/phpunit": "4.*|5.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "ParagonIE\\ConstantTime\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com", + "role": "Maintainer" + }, + { + "name": "Steve 'Sc00bz' Thomas", + "email": "steve@tobtu.com", + "homepage": "https://www.tobtu.com", + "role": "Original Developer" + } + ], + "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", + "keywords": [ + "base16", + "base32", + "base32_decode", + "base32_encode", + "base64", + "base64_decode", + "base64_encode", + "bin2hex", + "encoding", + "hex", + "hex2bin", + "rfc4648" + ], + "time": "2016-04-08 16:58:39" + }, + { + "name": "paragonie/random_compat", + "version": "v2.0.2", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "088c04e2f261c33bed6ca5245491cfca69195ccf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/088c04e2f261c33bed6ca5245491cfca69195ccf", + "reference": "088c04e2f261c33bed6ca5245491cfca69195ccf", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "autoload": { + "files": [ + "lib/random.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "pseudorandom", + "random" + ], + "time": "2016-04-03 06:00:07" + } + ], + "packages-dev": [ + { + "name": "doctrine/instantiator", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "shasum": "" + }, + "require": { + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2015-06-14 21:17:01" + }, + { + "name": "michelf/php-markdown", + "version": "1.6.0", + "source": { + "type": "git", + "url": "https://github.com/michelf/php-markdown.git", + "reference": "156e56ee036505ec637d761ee62dc425d807183c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/michelf/php-markdown/zipball/156e56ee036505ec637d761ee62dc425d807183c", + "reference": "156e56ee036505ec637d761ee62dc425d807183c", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-lib": "1.4.x-dev" + } + }, + "autoload": { + "psr-0": { + "Michelf": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Michel Fortin", + "email": "michel.fortin@michelf.ca", + "homepage": "https://michelf.ca/", + "role": "Developer" + }, + { + "name": "John Gruber", + "homepage": "https://daringfireball.net/" + } + ], + "description": "PHP Markdown", + "homepage": "https://michelf.ca/projects/php-markdown/", + "keywords": [ + "markdown" + ], + "time": "2015-12-24 01:37:31" + }, + { + "name": "nikic/php-parser", + "version": "v0.9.5", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "ef70767475434bdb3615b43c327e2cae17ef12eb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ef70767475434bdb3615b43c327e2cae17ef12eb", + "reference": "ef70767475434bdb3615b43c327e2cae17ef12eb", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.9-dev" + } + }, + "autoload": { + "psr-0": { + "PHPParser": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "time": "2014-07-23 18:24:17" + }, + { + "name": "phing/phing", + "version": "2.14.0", + "source": { + "type": "git", + "url": "https://github.com/phingofficial/phing.git", + "reference": "7dd73c83c377623def54b58121f46b4dcb35dd61" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phingofficial/phing/zipball/7dd73c83c377623def54b58121f46b4dcb35dd61", + "reference": "7dd73c83c377623def54b58121f46b4dcb35dd61", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "ext-pdo_sqlite": "*", + "lastcraft/simpletest": "@dev", + "mikey179/vfsstream": "^1.6", + "pdepend/pdepend": "2.x", + "pear/archive_tar": "1.4.x", + "pear/http_request2": "dev-trunk", + "pear/net_growl": "dev-trunk", + "pear/pear-core-minimal": "1.10.1", + "pear/versioncontrol_git": "@dev", + "pear/versioncontrol_svn": "~0.5", + "phpdocumentor/phpdocumentor": "2.x", + "phploc/phploc": "~2.0.6", + "phpmd/phpmd": "~2.2", + "phpunit/phpunit": ">=3.7", + "sebastian/git": "~1.0", + "sebastian/phpcpd": "2.x", + "squizlabs/php_codesniffer": "~2.2", + "symfony/yaml": "~2.7" + }, + "suggest": { + "pdepend/pdepend": "PHP version of JDepend", + "pear/archive_tar": "Tar file management class", + "pear/versioncontrol_git": "A library that provides OO interface to handle Git repository", + "pear/versioncontrol_svn": "A simple OO-style interface for Subversion, the free/open-source version control system", + "phpdocumentor/phpdocumentor": "Documentation Generator for PHP", + "phploc/phploc": "A tool for quickly measuring the size of a PHP project", + "phpmd/phpmd": "PHP version of PMD tool", + "phpunit/php-code-coverage": "Library that provides collection, processing, and rendering functionality for PHP code coverage information", + "phpunit/phpunit": "The PHP Unit Testing Framework", + "sebastian/phpcpd": "Copy/Paste Detector (CPD) for PHP code", + "tedivm/jshrink": "Javascript Minifier built in PHP" + }, + "bin": [ + "bin/phing" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.14.x-dev" + } + }, + "autoload": { + "classmap": [ + "classes/phing/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "classes" + ], + "license": [ + "LGPL-3.0" + ], + "authors": [ + { + "name": "Michiel Rook", + "email": "mrook@php.net" + }, + { + "name": "Phing Community", + "homepage": "https://www.phing.info/trac/wiki/Development/Contributors" + } + ], + "description": "PHing Is Not GNU make; it's a PHP project build system or build tool based on Apache Ant.", + "homepage": "https://www.phing.info/", + "keywords": [ + "build", + "phing", + "task", + "tool" + ], + "time": "2016-03-10 21:39:23" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", + "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "dflydev/markdown": "~1.0", + "erusev/parsedown": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "phpDocumentor": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "mike.vanriel@naenius.com" + } + ], + "time": "2015-02-03 12:10:50" + }, + { + "name": "phpspec/prophecy", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3c91bdf81797d725b14cb62906f9a4ce44235972", + "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "~2.0", + "sebastian/comparator": "~1.1", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "phpspec/phpspec": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2016-02-15 07:46:21" + }, + { + "name": "phpunit/php-code-coverage", + "version": "2.2.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "~1.3", + "sebastian/environment": "^1.3.2", + "sebastian/version": "~1.0" + }, + "require-dev": { + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "~4" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.2.1", + "ext-xmlwriter": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2015-10-06 15:47:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2015-06-21 13:08:43" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21 13:50:34" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4|~5" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2016-05-12 18:03:57" + }, + { + "name": "phpunit/php-token-stream", + "version": "1.4.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", + "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2015-09-15 10:49:45" + }, + { + "name": "phpunit/phpunit", + "version": "4.8.26", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "fc1d8cd5b5de11625979125c5639347896ac2c74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fc1d8cd5b5de11625979125c5639347896ac2c74", + "reference": "fc1d8cd5b5de11625979125c5639347896ac2c74", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.3.3", + "phpspec/prophecy": "^1.3.1", + "phpunit/php-code-coverage": "~2.1", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "~2.3", + "sebastian/comparator": "~1.1", + "sebastian/diff": "~1.2", + "sebastian/environment": "~1.3", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", + "sebastian/version": "~1.0", + "symfony/yaml": "~2.1|~3.0" + }, + "suggest": { + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.8.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2016-05-17 03:09:28" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "2.3.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": ">=5.3.3", + "phpunit/php-text-template": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "time": "2015-10-02 06:51:40" + }, + { + "name": "pimple/pimple", + "version": "v2.1.1", + "source": { + "type": "git", + "url": "https://github.com/silexphp/Pimple.git", + "reference": "ea22fb2880faf7b7b0e17c9809c6fe25b071fd76" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/ea22fb2880faf7b7b0e17c9809c6fe25b071fd76", + "reference": "ea22fb2880faf7b7b0e17c9809c6fe25b071fd76", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1.x-dev" + } + }, + "autoload": { + "psr-0": { + "Pimple": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Pimple is a simple Dependency Injection Container for PHP 5.3", + "homepage": "http://pimple.sensiolabs.org", + "keywords": [ + "container", + "dependency injection" + ], + "time": "2014-07-24 07:10:08" + }, + { + "name": "sami/sami", + "version": "v2.0.0", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfPHP/Sami.git", + "reference": "fa58b324f41aa2aefe21dac4f22d8c98965fc012" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfPHP/Sami/zipball/fa58b324f41aa2aefe21dac4f22d8c98965fc012", + "reference": "fa58b324f41aa2aefe21dac4f22d8c98965fc012", + "shasum": "" + }, + "require": { + "michelf/php-markdown": "~1.3", + "nikic/php-parser": "0.9.*", + "php": ">=5.3.0", + "pimple/pimple": "2.*", + "symfony/console": "~2.1", + "symfony/filesystem": "~2.1", + "symfony/finder": "~2.1", + "symfony/process": "~2.1", + "symfony/yaml": "~2.1", + "twig/twig": "1.*" + }, + "bin": [ + "sami.php" + ], + "type": "application", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-0": { + "Sami": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Sami, an API documentation generator", + "homepage": "http://sami.sensiolabs.org", + "keywords": [ + "phpdoc" + ], + "time": "2014-06-25 12:05:18" + }, + { + "name": "sebastian/comparator", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2015-07-26 15:48:44" + }, + { + "name": "sebastian/diff", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2015-12-08 07:14:41" + }, + { + "name": "sebastian/environment", + "version": "1.3.7", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716", + "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2016-05-17 03:18:57" + }, + { + "name": "sebastian/exporter", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "7ae5513327cb536431847bcc0c10edba2701064e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e", + "reference": "7ae5513327cb536431847bcc0c10edba2701064e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2015-06-21 07:55:53" + }, + { + "name": "sebastian/global-state", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2015-10-12 03:26:01" + }, + { + "name": "sebastian/recursion-context", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "913401df809e99e4f47b27cdd781f4a258d58791" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", + "reference": "913401df809e99e4f47b27cdd781f4a258d58791", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2015-11-11 19:50:13" + }, + { + "name": "sebastian/version", + "version": "1.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "shasum": "" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2015-06-21 13:59:46" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "2.6.0", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "1bcdf03b068a530ac1962ce671dead356eeba43b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1bcdf03b068a530ac1962ce671dead356eeba43b", + "reference": "1bcdf03b068a530ac1962ce671dead356eeba43b", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "bin": [ + "scripts/phpcs", + "scripts/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "classmap": [ + "CodeSniffer.php", + "CodeSniffer/CLI.php", + "CodeSniffer/Exception.php", + "CodeSniffer/File.php", + "CodeSniffer/Fixer.php", + "CodeSniffer/Report.php", + "CodeSniffer/Reporting.php", + "CodeSniffer/Sniff.php", + "CodeSniffer/Tokens.php", + "CodeSniffer/Reports/", + "CodeSniffer/Tokenizers/", + "CodeSniffer/DocGenerators/", + "CodeSniffer/Standards/AbstractPatternSniff.php", + "CodeSniffer/Standards/AbstractScopeSniff.php", + "CodeSniffer/Standards/AbstractVariableSniff.php", + "CodeSniffer/Standards/IncorrectPatternException.php", + "CodeSniffer/Standards/Generic/Sniffs/", + "CodeSniffer/Standards/MySource/Sniffs/", + "CodeSniffer/Standards/PEAR/Sniffs/", + "CodeSniffer/Standards/PSR1/Sniffs/", + "CodeSniffer/Standards/PSR2/Sniffs/", + "CodeSniffer/Standards/Squiz/Sniffs/", + "CodeSniffer/Standards/Zend/Sniffs/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "http://www.squizlabs.com/php-codesniffer", + "keywords": [ + "phpcs", + "standards" + ], + "time": "2016-04-03 22:58:34" + }, + { + "name": "symfony/console", + "version": "v2.8.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "48221d3de4dc22d2cd57c97e8b9361821da86609" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/48221d3de4dc22d2cd57c97e8b9361821da86609", + "reference": "48221d3de4dc22d2cd57c97e8b9361821da86609", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/event-dispatcher": "~2.1|~3.0.0", + "symfony/process": "~2.1|~3.0.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2016-04-26 12:00:47" + }, + { + "name": "symfony/filesystem", + "version": "v2.8.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "dee379131dceed90a429e951546b33edfe7dccbb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/dee379131dceed90a429e951546b33edfe7dccbb", + "reference": "dee379131dceed90a429e951546b33edfe7dccbb", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2016-04-12 18:01:21" + }, + { + "name": "symfony/finder", + "version": "v2.8.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "ca24cf2cd4e3826f571e0067e535758e73807aa1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/ca24cf2cd4e3826f571e0067e535758e73807aa1", + "reference": "ca24cf2cd4e3826f571e0067e535758e73807aa1", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2016-03-10 10:53:53" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "dff51f72b0706335131b00a7f49606168c582594" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594", + "reference": "dff51f72b0706335131b00a7f49606168c582594", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2016-05-18 14:26:46" + }, + { + "name": "symfony/process", + "version": "v2.8.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "1276bd9be89be039748cf753a2137f4ef149cd74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/1276bd9be89be039748cf753a2137f4ef149cd74", + "reference": "1276bd9be89be039748cf753a2137f4ef149cd74", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Process Component", + "homepage": "https://symfony.com", + "time": "2016-04-14 15:22:22" + }, + { + "name": "symfony/yaml", + "version": "v2.8.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "e4fbcc65f90909c999ac3b4dfa699ee6563a9940" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/e4fbcc65f90909c999ac3b4dfa699ee6563a9940", + "reference": "e4fbcc65f90909c999ac3b4dfa699ee6563a9940", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2016-03-29 19:00:15" + }, + { + "name": "twig/twig", + "version": "v1.24.0", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "3e5aa30ebfbafd5951fb1b01e338e1800ce7e0e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/3e5aa30ebfbafd5951fb1b01e338e1800ce7e0e8", + "reference": "3e5aa30ebfbafd5951fb1b01e338e1800ce7e0e8", + "shasum": "" + }, + "require": { + "php": ">=5.2.7" + }, + "require-dev": { + "symfony/debug": "~2.7", + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.24-dev" + } + }, + "autoload": { + "psr-0": { + "Twig_": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + }, + { + "name": "Twig Team", + "homepage": "http://twig.sensiolabs.org/contributors", + "role": "Contributors" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "http://twig.sensiolabs.org", + "keywords": [ + "templating" + ], + "time": "2016-01-25 21:22:18" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=5.3.3" + }, + "platform-dev": [] +} diff --git a/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/MSBLOB.php b/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/MSBLOB.php new file mode 100644 index 0000000000..b99dc2f068 --- /dev/null +++ b/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/MSBLOB.php @@ -0,0 +1,224 @@ + + * @copyright 2015 Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net + */ + +namespace phpseclib\Crypt\RSA; + +use ParagonIE\ConstantTime\Base64; +use phpseclib\Math\BigInteger; + +/** + * Microsoft BLOB Formatted RSA Key Handler + * + * @package RSA + * @author Jim Wigginton + * @access public + */ +class MSBLOB +{ + /**#@+ + * @access private + */ + /** + * Public/Private Key Pair + */ + const PRIVATEKEYBLOB = 0x7; + /** + * Public Key + */ + const PUBLICKEYBLOB = 0x6; + /** + * Public Key + */ + const PUBLICKEYBLOBEX = 0xA; + /** + * RSA public key exchange algorithm + */ + const CALG_RSA_KEYX = 0x0000A400; + /** + * RSA public key exchange algorithm + */ + const CALG_RSA_SIGN = 0x00002400; + /** + * Public Key + */ + const RSA1 = 0x31415352; + /** + * Private Key + */ + const RSA2 = 0x32415352; + /**#@-*/ + + /** + * Break a public or private key down into its constituent components + * + * @access public + * @param string $key + * @param string $password optional + * @return array + */ + static function load($key, $password = '') + { + if (!is_string($key)) { + return false; + } + + $key = Base64::decode($key); + + if (!is_string($key) || strlen($key) < 20) { + return false; + } + + // PUBLICKEYSTRUC publickeystruc + // https://msdn.microsoft.com/en-us/library/windows/desktop/aa387453(v=vs.85).aspx + extract(unpack('atype/aversion/vreserved/Valgo', self::_string_shift($key, 8))); + switch (ord($type)) { + case self::PUBLICKEYBLOB: + case self::PUBLICKEYBLOBEX: + $publickey = true; + break; + case self::PRIVATEKEYBLOB: + $publickey = false; + break; + default: + return false; + } + + $components = array('isPublicKey' => $publickey); + + // https://msdn.microsoft.com/en-us/library/windows/desktop/aa375549(v=vs.85).aspx + switch ($algo) { + case self::CALG_RSA_KEYX: + case self::CALG_RSA_SIGN: + break; + default: + return false; + } + + // RSAPUBKEY rsapubkey + // https://msdn.microsoft.com/en-us/library/windows/desktop/aa387685(v=vs.85).aspx + // could do V for pubexp but that's unsigned 32-bit whereas some PHP installs only do signed 32-bit + extract(unpack('Vmagic/Vbitlen/a4pubexp', self::_string_shift($key, 12))); + switch ($magic) { + case self::RSA2: + $components['isPublicKey'] = false; + case self::RSA1: + break; + default: + return false; + } + + $baseLength = $bitlen / 16; + if (strlen($key) != 2 * $baseLength && strlen($key) != 9 * $baseLength) { + return false; + } + + $components[$components['isPublicKey'] ? 'publicExponent' : 'privateExponent'] = new BigInteger(strrev($pubexp), 256); + // BYTE modulus[rsapubkey.bitlen/8] + $components['modulus'] = new BigInteger(strrev(self::_string_shift($key, $bitlen / 8)), 256); + + if ($publickey) { + return $components; + } + + $components['isPublicKey'] = false; + + // BYTE prime1[rsapubkey.bitlen/16] + $components['primes'] = array(1 => new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256)); + // BYTE prime2[rsapubkey.bitlen/16] + $components['primes'][] = new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256); + // BYTE exponent1[rsapubkey.bitlen/16] + $components['exponents'] = array(1 => new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256)); + // BYTE exponent2[rsapubkey.bitlen/16] + $components['exponents'][] = new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256); + // BYTE coefficient[rsapubkey.bitlen/16] + $components['coefficients'] = array(2 => new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256)); + if (isset($components['privateExponent'])) { + $components['publicExponent'] = $components['privateExponent']; + } + // BYTE privateExponent[rsapubkey.bitlen/8] + $components['privateExponent'] = new BigInteger(strrev(self::_string_shift($key, $bitlen / 8)), 256); + + return $components; + } + + /** + * Convert a private key to the appropriate format. + * + * @access public + * @param \phpseclib\Math\BigInteger $n + * @param \phpseclib\Math\BigInteger $e + * @param \phpseclib\Math\BigInteger $d + * @param array $primes + * @param array $exponents + * @param array $coefficients + * @param string $password optional + * @return string + */ + static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '') + { + $n = strrev($n->toBytes()); + $e = str_pad(strrev($e->toBytes()), 4, "\0"); + $key = pack('aavV', chr(self::PRIVATEKEYBLOB), chr(2), 0, self::CALG_RSA_KEYX); + $key.= pack('VVa*', self::RSA2, 8 * strlen($n), $e); + $key.= $n; + $key.= strrev($primes[1]->toBytes()); + $key.= strrev($primes[2]->toBytes()); + $key.= strrev($exponents[1]->toBytes()); + $key.= strrev($exponents[2]->toBytes()); + $key.= strrev($coefficients[1]->toBytes()); + $key.= strrev($d->toBytes()); + + return Base64::encode($key); + } + + /** + * Convert a public key to the appropriate format + * + * @access public + * @param \phpseclib\Math\BigInteger $n + * @param \phpseclib\Math\BigInteger $e + * @return string + */ + static function savePublicKey(BigInteger $n, BigInteger $e) + { + $n = strrev($n->toBytes()); + $e = str_pad(strrev($e->toBytes()), 4, "\0"); + $key = pack('aavV', chr(self::PUBLICKEYBLOB), chr(2), 0, self::CALG_RSA_KEYX); + $key.= pack('VVa*', self::RSA1, 8 * strlen($n), $e); + $key.= $n; + + return Base64::encode($key); + } + + /** + * String Shift + * + * Inspired by array_shift + * + * @param string $string + * @param int $index + * @return string + * @access private + */ + static function _string_shift(&$string, $index = 1) + { + $substr = substr($string, 0, $index); + $string = substr($string, $index); + return $substr; + } +} diff --git a/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/OpenSSH.php b/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/OpenSSH.php new file mode 100644 index 0000000000..8cd5328282 --- /dev/null +++ b/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/OpenSSH.php @@ -0,0 +1,141 @@ + + * @copyright 2015 Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net + */ + +namespace phpseclib\Crypt\RSA; + +use ParagonIE\ConstantTime\Base64; +use phpseclib\Math\BigInteger; + +/** + * OpenSSH Formatted RSA Key Handler + * + * @package RSA + * @author Jim Wigginton + * @access public + */ +class OpenSSH +{ + /** + * Default comment + * + * @var string + * @access private + */ + static $comment = 'phpseclib-generated-key'; + + /** + * Sets the default comment + * + * @access public + * @param string $comment + */ + static function setComment($comment) + { + self::$comment = str_replace(array("\r", "\n"), '', $comment); + } + + /** + * Break a public or private key down into its constituent components + * + * @access public + * @param string $key + * @param string $password optional + * @return array + */ + static function load($key, $password = '') + { + if (!is_string($key)) { + return false; + } + + $parts = explode(' ', $key, 3); + + $key = isset($parts[1]) ? Base64::decode($parts[1]) : Base64::decode($parts[0]); + if ($key === false) { + return false; + } + + $comment = isset($parts[2]) ? $parts[2] : false; + + if (substr($key, 0, 11) != "\0\0\0\7ssh-rsa") { + return false; + } + self::_string_shift($key, 11); + if (strlen($key) <= 4) { + return false; + } + extract(unpack('Nlength', self::_string_shift($key, 4))); + if (strlen($key) <= $length) { + return false; + } + $publicExponent = new BigInteger(self::_string_shift($key, $length), -256); + if (strlen($key) <= 4) { + return false; + } + extract(unpack('Nlength', self::_string_shift($key, 4))); + if (strlen($key) != $length) { + return false; + } + $modulus = new BigInteger(self::_string_shift($key, $length), -256); + + return array( + 'isPublicKey' => true, + 'modulus' => $modulus, + 'publicExponent' => $publicExponent, + 'comment' => $comment + ); + } + + /** + * Convert a public key to the appropriate format + * + * @access public + * @param \phpseclib\Math\BigInteger $n + * @param \phpseclib\Math\BigInteger $e + * @return string + */ + static function savePublicKey(BigInteger $n, BigInteger $e) + { + $publicExponent = $e->toBytes(true); + $modulus = $n->toBytes(true); + + // from : + // string "ssh-rsa" + // mpint e + // mpint n + $RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus); + $RSAPublicKey = 'ssh-rsa ' . Base64::encode($RSAPublicKey) . ' ' . self::$comment; + + return $RSAPublicKey; + } + + /** + * String Shift + * + * Inspired by array_shift + * + * @param string $string + * @param int $index + * @return string + * @access private + */ + static function _string_shift(&$string, $index = 1) + { + $substr = substr($string, 0, $index); + $string = substr($string, $index); + return $substr; + } +} diff --git a/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PKCS.php b/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PKCS.php new file mode 100644 index 0000000000..b0ff2559ed --- /dev/null +++ b/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PKCS.php @@ -0,0 +1,487 @@ + + * @copyright 2015 Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net + */ + +namespace phpseclib\Crypt\RSA; + +use ParagonIE\ConstantTime\Base64; +use ParagonIE\ConstantTime\Hex; +use phpseclib\Crypt\AES; +use phpseclib\Crypt\Base; +use phpseclib\Crypt\DES; +use phpseclib\Crypt\TripleDES; +use phpseclib\Math\BigInteger; + +/** + * PKCS Formatted RSA Key Handler + * + * @package RSA + * @author Jim Wigginton + * @access public + */ +abstract class PKCS +{ + /**#@+ + * @access private + * @see \phpseclib\Crypt\RSA::createKey() + */ + /** + * ASN1 Integer + */ + const ASN1_INTEGER = 2; + /** + * ASN1 Bit String + */ + const ASN1_BITSTRING = 3; + /** + * ASN1 Octet String + */ + const ASN1_OCTETSTRING = 4; + /** + * ASN1 Object Identifier + */ + const ASN1_OBJECT = 6; + /** + * ASN1 Sequence (with the constucted bit set) + */ + const ASN1_SEQUENCE = 48; + /**#@-*/ + + /**#@+ + * @access private + */ + /** + * Auto-detect the format + */ + const MODE_ANY = 0; + /** + * Require base64-encoded PEM's be supplied + */ + const MODE_PEM = 1; + /** + * Require raw DER's be supplied + */ + const MODE_DER = 2; + /**#@-*/ + + /** + * Is the key a base-64 encoded PEM, DER or should it be auto-detected? + * + * @access private + * @param int + */ + static $format = self::MODE_ANY; + + /** + * Returns the mode constant corresponding to the mode string + * + * @access public + * @param string $mode + * @return int + * @throws \UnexpectedValueException if the block cipher mode is unsupported + */ + static function getEncryptionMode($mode) + { + switch ($mode) { + case 'CBC': + return Base::MODE_CBC; + case 'ECB': + return Base::MODE_ECB; + case 'CFB': + return Base::MODE_CFB; + case 'OFB': + return Base::MODE_OFB; + case 'CTR': + return Base::MODE_CTR; + } + throw new \UnexpectedValueException('Unsupported block cipher mode of operation'); + } + + /** + * Returns a cipher object corresponding to a string + * + * @access public + * @param string $algo + * @return string + * @throws \UnexpectedValueException if the encryption algorithm is unsupported + */ + static function getEncryptionObject($algo) + { + $modes = '(CBC|ECB|CFB|OFB|CTR)'; + switch (true) { + case preg_match("#^AES-(128|192|256)-$modes$#", $algo, $matches): + $cipher = new AES(self::getEncryptionMode($matches[2])); + $cipher->setKeyLength($matches[1]); + return $cipher; + case preg_match("#^DES-EDE3-$modes$#", $algo, $matches): + return new TripleDES(self::getEncryptionMode($matches[1])); + case preg_match("#^DES-$modes$#", $algo, $matches): + return new DES(self::getEncryptionMode($matches[1])); + default: + throw new \UnexpectedValueException('Unsupported encryption algorithmn'); + } + } + + /** + * Generate a symmetric key for PKCS#1 keys + * + * @access public + * @param string $password + * @param string $iv + * @param int $length + * @return string + */ + static function generateSymmetricKey($password, $iv, $length) + { + $symkey = ''; + $iv = substr($iv, 0, 8); + while (strlen($symkey) < $length) { + $symkey.= md5($symkey . $password . $iv, true); + } + return substr($symkey, 0, $length); + } + + /** + * Break a public or private key down into its constituent components + * + * @access public + * @param string $key + * @param string $password optional + * @return array + */ + static function load($key, $password = '') + { + if (!is_string($key)) { + return false; + } + + $components = array('isPublicKey' => strpos($key, 'PUBLIC') !== false); + + /* Although PKCS#1 proposes a format that public and private keys can use, encrypting them is + "outside the scope" of PKCS#1. PKCS#1 then refers you to PKCS#12 and PKCS#15 if you're wanting to + protect private keys, however, that's not what OpenSSL* does. OpenSSL protects private keys by adding + two new "fields" to the key - DEK-Info and Proc-Type. These fields are discussed here: + + http://tools.ietf.org/html/rfc1421#section-4.6.1.1 + http://tools.ietf.org/html/rfc1421#section-4.6.1.3 + + DES-EDE3-CBC as an algorithm, however, is not discussed anywhere, near as I can tell. + DES-CBC and DES-EDE are discussed in RFC1423, however, DES-EDE3-CBC isn't, nor is its key derivation + function. As is, the definitive authority on this encoding scheme isn't the IETF but rather OpenSSL's + own implementation. ie. the implementation *is* the standard and any bugs that may exist in that + implementation are part of the standard, as well. + + * OpenSSL is the de facto standard. It's utilized by OpenSSH and other projects */ + if (preg_match('#DEK-Info: (.+),(.+)#', $key, $matches)) { + $iv = Hex::decode(trim($matches[2])); + // remove the Proc-Type / DEK-Info sections as they're no longer needed + $key = preg_replace('#^(?:Proc-Type|DEK-Info): .*#m', '', $key); + $ciphertext = self::_extractBER($key); + if ($ciphertext === false) { + $ciphertext = $key; + } + $crypto = self::getEncryptionObject($matches[1]); + $crypto->setKey(self::generateSymmetricKey($password, $iv, $crypto->getKeyLength() >> 3)); + $crypto->setIV($iv); + $key = $crypto->decrypt($ciphertext); + if ($key === false) { + return false; + } + } else { + if (self::$format != self::MODE_DER) { + $decoded = self::_extractBER($key); + if ($decoded !== false) { + $key = $decoded; + } elseif (self::$format == self::MODE_PEM) { + return false; + } + } + } + + if (ord(self::_string_shift($key)) != self::ASN1_SEQUENCE) { + return false; + } + if (self::_decodeLength($key) != strlen($key)) { + return false; + } + + $tag = ord(self::_string_shift($key)); + /* intended for keys for which OpenSSL's asn1parse returns the following: + + 0:d=0 hl=4 l= 631 cons: SEQUENCE + 4:d=1 hl=2 l= 1 prim: INTEGER :00 + 7:d=1 hl=2 l= 13 cons: SEQUENCE + 9:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption + 20:d=2 hl=2 l= 0 prim: NULL + 22:d=1 hl=4 l= 609 prim: OCTET STRING + + ie. PKCS8 keys */ + + if ($tag == self::ASN1_INTEGER && substr($key, 0, 3) == "\x01\x00\x30") { + self::_string_shift($key, 3); + $tag = self::ASN1_SEQUENCE; + } + + if ($tag == self::ASN1_SEQUENCE) { + $temp = self::_string_shift($key, self::_decodeLength($key)); + if (ord(self::_string_shift($temp)) != self::ASN1_OBJECT) { + return false; + } + $length = self::_decodeLength($temp); + switch (self::_string_shift($temp, $length)) { + case "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01": // rsaEncryption + break; + case "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03": // pbeWithMD5AndDES-CBC + /* + PBEParameter ::= SEQUENCE { + salt OCTET STRING (SIZE(8)), + iterationCount INTEGER } + */ + if (ord(self::_string_shift($temp)) != self::ASN1_SEQUENCE) { + return false; + } + if (self::_decodeLength($temp) != strlen($temp)) { + return false; + } + self::_string_shift($temp); // assume it's an octet string + $salt = self::_string_shift($temp, self::_decodeLength($temp)); + if (ord(self::_string_shift($temp)) != self::ASN1_INTEGER) { + return false; + } + self::_decodeLength($temp); + list(, $iterationCount) = unpack('N', str_pad($temp, 4, chr(0), STR_PAD_LEFT)); + self::_string_shift($key); // assume it's an octet string + $length = self::_decodeLength($key); + if (strlen($key) != $length) { + return false; + } + + $crypto = new DES(DES::MODE_CBC); + $crypto->setPassword($password, 'pbkdf1', 'md5', $salt, $iterationCount); + $key = $crypto->decrypt($key); + if ($key === false) { + return false; + } + return self::load($key); + default: + return false; + } + /* intended for keys for which OpenSSL's asn1parse returns the following: + + 0:d=0 hl=4 l= 290 cons: SEQUENCE + 4:d=1 hl=2 l= 13 cons: SEQUENCE + 6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption + 17:d=2 hl=2 l= 0 prim: NULL + 19:d=1 hl=4 l= 271 prim: BIT STRING */ + $tag = ord(self::_string_shift($key)); // skip over the BIT STRING / OCTET STRING tag + self::_decodeLength($key); // skip over the BIT STRING / OCTET STRING length + // "The initial octet shall encode, as an unsigned binary integer wtih bit 1 as the least significant bit, the number of + // unused bits in the final subsequent octet. The number shall be in the range zero to seven." + // -- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf (section 8.6.2.2) + if ($tag == self::ASN1_BITSTRING) { + self::_string_shift($key); + } + if (ord(self::_string_shift($key)) != self::ASN1_SEQUENCE) { + return false; + } + if (self::_decodeLength($key) != strlen($key)) { + return false; + } + $tag = ord(self::_string_shift($key)); + } + if ($tag != self::ASN1_INTEGER) { + return false; + } + + $length = self::_decodeLength($key); + $temp = self::_string_shift($key, $length); + if (strlen($temp) != 1 || ord($temp) > 2) { + $components['modulus'] = new BigInteger($temp, 256); + self::_string_shift($key); // skip over self::ASN1_INTEGER + $length = self::_decodeLength($key); + $components[$components['isPublicKey'] ? 'publicExponent' : 'privateExponent'] = new BigInteger(self::_string_shift($key, $length), 256); + + return $components; + } + if (ord(self::_string_shift($key)) != self::ASN1_INTEGER) { + return false; + } + $length = self::_decodeLength($key); + $components['modulus'] = new BigInteger(self::_string_shift($key, $length), 256); + self::_string_shift($key); + $length = self::_decodeLength($key); + $components['publicExponent'] = new BigInteger(self::_string_shift($key, $length), 256); + self::_string_shift($key); + $length = self::_decodeLength($key); + $components['privateExponent'] = new BigInteger(self::_string_shift($key, $length), 256); + self::_string_shift($key); + $length = self::_decodeLength($key); + $components['primes'] = array(1 => new BigInteger(self::_string_shift($key, $length), 256)); + self::_string_shift($key); + $length = self::_decodeLength($key); + $components['primes'][] = new BigInteger(self::_string_shift($key, $length), 256); + self::_string_shift($key); + $length = self::_decodeLength($key); + $components['exponents'] = array(1 => new BigInteger(self::_string_shift($key, $length), 256)); + self::_string_shift($key); + $length = self::_decodeLength($key); + $components['exponents'][] = new BigInteger(self::_string_shift($key, $length), 256); + self::_string_shift($key); + $length = self::_decodeLength($key); + $components['coefficients'] = array(2 => new BigInteger(self::_string_shift($key, $length), 256)); + + if (!empty($key)) { + if (ord(self::_string_shift($key)) != self::ASN1_SEQUENCE) { + return false; + } + self::_decodeLength($key); + while (!empty($key)) { + if (ord(self::_string_shift($key)) != self::ASN1_SEQUENCE) { + return false; + } + self::_decodeLength($key); + $key = substr($key, 1); + $length = self::_decodeLength($key); + $components['primes'][] = new BigInteger(self::_string_shift($key, $length), 256); + self::_string_shift($key); + $length = self::_decodeLength($key); + $components['exponents'][] = new BigInteger(self::_string_shift($key, $length), 256); + self::_string_shift($key); + $length = self::_decodeLength($key); + $components['coefficients'][] = new BigInteger(self::_string_shift($key, $length), 256); + } + } + + return $components; + } + + /** + * Require base64-encoded PEM's be supplied + * + * @see self::load() + * @access public + */ + static function requirePEM() + { + self::$format = self::MODE_PEM; + } + + /** + * Require raw DER's be supplied + * + * @see self::load() + * @access public + */ + static function requireDER() + { + self::$format = self::MODE_DER; + } + + /** + * Accept any format and auto detect the format + * + * This is the default setting + * + * @see self::load() + * @access public + */ + static function requireAny() + { + self::$format = self::MODE_ANY; + } + + /** + * DER-decode the length + * + * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See + * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information. + * + * @access private + * @param string $string + * @return int + */ + static function _decodeLength(&$string) + { + $length = ord(self::_string_shift($string)); + if ($length & 0x80) { // definite length, long form + $length&= 0x7F; + $temp = self::_string_shift($string, $length); + list(, $length) = unpack('N', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4)); + } + return $length; + } + + /** + * DER-encode the length + * + * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See + * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information. + * + * @access private + * @param int $length + * @return string + */ + static function _encodeLength($length) + { + if ($length <= 0x7F) { + return chr($length); + } + + $temp = ltrim(pack('N', $length), chr(0)); + return pack('Ca*', 0x80 | strlen($temp), $temp); + } + + /** + * String Shift + * + * Inspired by array_shift + * + * @param string $string + * @param int $index + * @return string + * @access private + */ + static function _string_shift(&$string, $index = 1) + { + $substr = substr($string, 0, $index); + $string = substr($string, $index); + return $substr; + } + + /** + * Extract raw BER from Base64 encoding + * + * @access private + * @param string $str + * @return string + */ + static function _extractBER($str) + { + /* X.509 certs are assumed to be base64 encoded but sometimes they'll have additional things in them + * above and beyond the ceritificate. + * ie. some may have the following preceding the -----BEGIN CERTIFICATE----- line: + * + * Bag Attributes + * localKeyID: 01 00 00 00 + * subject=/O=organization/OU=org unit/CN=common name + * issuer=/O=organization/CN=common name + */ + $temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1); + // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff + $temp = preg_replace('#-+[^-]+-+#', '', $temp); + // remove new lines + $temp = str_replace(array("\r", "\n", ' '), '', $temp); + $temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? Base64::decode($temp) : false; + return $temp != false ? $temp : $str; + } +} diff --git a/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PKCS1.php b/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PKCS1.php new file mode 100644 index 0000000000..e5d6e1d64f --- /dev/null +++ b/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PKCS1.php @@ -0,0 +1,174 @@ + + * @copyright 2015 Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net + */ + +namespace phpseclib\Crypt\RSA; + +use ParagonIE\ConstantTime\Base64; +use ParagonIE\ConstantTime\Hex; +use phpseclib\Crypt\AES; +use phpseclib\Crypt\DES; +use phpseclib\Crypt\Random; +use phpseclib\Crypt\TripleDES; +use phpseclib\Math\BigInteger; + +/** + * PKCS#1 Formatted RSA Key Handler + * + * @package RSA + * @author Jim Wigginton + * @access public + */ +class PKCS1 extends PKCS +{ + /** + * Default encryption algorithm + * + * @var string + * @access private + */ + static $defaultEncryptionAlgorithm = 'DES-EDE3-CBC'; + + /** + * Sets the default encryption algorithm + * + * @access public + * @param string $algo + */ + static function setEncryptionAlgorithm($algo) + { + self::$defaultEncryptionAlgorithm = $algo; + } + + /** + * Convert a private key to the appropriate format. + * + * @access public + * @param \phpseclib\Math\BigInteger $n + * @param \phpseclib\Math\BigInteger $e + * @param \phpseclib\Math\BigInteger $d + * @param array $primes + * @param array $exponents + * @param array $coefficients + * @param string $password optional + * @return string + */ + static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '') + { + $num_primes = count($primes); + $raw = array( + 'version' => $num_primes == 2 ? chr(0) : chr(1), // two-prime vs. multi + 'modulus' => $n->toBytes(true), + 'publicExponent' => $e->toBytes(true), + 'privateExponent' => $d->toBytes(true), + 'prime1' => $primes[1]->toBytes(true), + 'prime2' => $primes[2]->toBytes(true), + 'exponent1' => $exponents[1]->toBytes(true), + 'exponent2' => $exponents[2]->toBytes(true), + 'coefficient' => $coefficients[2]->toBytes(true) + ); + + $components = array(); + foreach ($raw as $name => $value) { + $components[$name] = pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($value)), $value); + } + + $RSAPrivateKey = implode('', $components); + + if ($num_primes > 2) { + $OtherPrimeInfos = ''; + for ($i = 3; $i <= $num_primes; $i++) { + // OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo + // + // OtherPrimeInfo ::= SEQUENCE { + // prime INTEGER, -- ri + // exponent INTEGER, -- di + // coefficient INTEGER -- ti + // } + $OtherPrimeInfo = pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($primes[$i]->toBytes(true))), $primes[$i]->toBytes(true)); + $OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($exponents[$i]->toBytes(true))), $exponents[$i]->toBytes(true)); + $OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($coefficients[$i]->toBytes(true))), $coefficients[$i]->toBytes(true)); + $OtherPrimeInfos.= pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($OtherPrimeInfo)), $OtherPrimeInfo); + } + $RSAPrivateKey.= pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($OtherPrimeInfos)), $OtherPrimeInfos); + } + + $RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey); + + if (!empty($password) || is_string($password)) { + $cipher = self::getEncryptionObject(self::$defaultEncryptionAlgorithm); + $iv = Random::string($cipher->getBlockLength() >> 3); + $cipher->setKey(self::generateSymmetricKey($password, $iv, $cipher->getKeyLength() >> 3)); + $cipher->setIV($iv); + $iv = strtoupper(Hex::encode($iv)); + $RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" . + "Proc-Type: 4,ENCRYPTED\r\n" . + "DEK-Info: " . self::$defaultEncryptionAlgorithm . ",$iv\r\n" . + "\r\n" . + chunk_split(Base64::encode($cipher->encrypt($RSAPrivateKey)), 64) . + '-----END RSA PRIVATE KEY-----'; + } else { + $RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" . + chunk_split(Base64::encode($RSAPrivateKey), 64) . + '-----END RSA PRIVATE KEY-----'; + } + + return $RSAPrivateKey; + } + + /** + * Convert a public key to the appropriate format + * + * @access public + * @param \phpseclib\Math\BigInteger $n + * @param \phpseclib\Math\BigInteger $e + * @return string + */ + static function savePublicKey(BigInteger $n, BigInteger $e) + { + $modulus = $n->toBytes(true); + $publicExponent = $e->toBytes(true); + + // from : + // RSAPublicKey ::= SEQUENCE { + // modulus INTEGER, -- n + // publicExponent INTEGER -- e + // } + $components = array( + 'modulus' => pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($modulus)), $modulus), + 'publicExponent' => pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($publicExponent)), $publicExponent) + ); + + $RSAPublicKey = pack( + 'Ca*a*a*', + self::ASN1_SEQUENCE, + self::_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])), + $components['modulus'], + $components['publicExponent'] + ); + + $RSAPublicKey = "-----BEGIN RSA PUBLIC KEY-----\r\n" . + chunk_split(Base64::encode($RSAPublicKey), 64) . + '-----END RSA PUBLIC KEY-----'; + + return $RSAPublicKey; + } +} diff --git a/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PKCS8.php b/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PKCS8.php new file mode 100644 index 0000000000..787c89a58a --- /dev/null +++ b/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PKCS8.php @@ -0,0 +1,209 @@ + + * @copyright 2015 Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net + */ + +namespace phpseclib\Crypt\RSA; + +use ParagonIE\ConstantTime\Base64; +use phpseclib\Crypt\DES; +use phpseclib\Crypt\Random; +use phpseclib\Math\BigInteger; + +/** + * PKCS#8 Formatted RSA Key Handler + * + * @package RSA + * @author Jim Wigginton + * @access public + */ +class PKCS8 extends PKCS +{ + /** + * Convert a private key to the appropriate format. + * + * @access public + * @param \phpseclib\Math\BigInteger $n + * @param \phpseclib\Math\BigInteger $e + * @param \phpseclib\Math\BigInteger $d + * @param array $primes + * @param array $exponents + * @param array $coefficients + * @param string $password optional + * @return string + */ + static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '') + { + $num_primes = count($primes); + $raw = array( + 'version' => $num_primes == 2 ? chr(0) : chr(1), // two-prime vs. multi + 'modulus' => $n->toBytes(true), + 'publicExponent' => $e->toBytes(true), + 'privateExponent' => $d->toBytes(true), + 'prime1' => $primes[1]->toBytes(true), + 'prime2' => $primes[2]->toBytes(true), + 'exponent1' => $exponents[1]->toBytes(true), + 'exponent2' => $exponents[2]->toBytes(true), + 'coefficient' => $coefficients[2]->toBytes(true) + ); + + $components = array(); + foreach ($raw as $name => $value) { + $components[$name] = pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($value)), $value); + } + + $RSAPrivateKey = implode('', $components); + + if ($num_primes > 2) { + $OtherPrimeInfos = ''; + for ($i = 3; $i <= $num_primes; $i++) { + // OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo + // + // OtherPrimeInfo ::= SEQUENCE { + // prime INTEGER, -- ri + // exponent INTEGER, -- di + // coefficient INTEGER -- ti + // } + $OtherPrimeInfo = pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($primes[$i]->toBytes(true))), $primes[$i]->toBytes(true)); + $OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($exponents[$i]->toBytes(true))), $exponents[$i]->toBytes(true)); + $OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($coefficients[$i]->toBytes(true))), $coefficients[$i]->toBytes(true)); + $OtherPrimeInfos.= pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($OtherPrimeInfo)), $OtherPrimeInfo); + } + $RSAPrivateKey.= pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($OtherPrimeInfos)), $OtherPrimeInfos); + } + + $RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey); + + $rsaOID = "\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00"; // hex version of MA0GCSqGSIb3DQEBAQUA + $RSAPrivateKey = pack( + 'Ca*a*Ca*a*', + self::ASN1_INTEGER, + "\01\00", + $rsaOID, + 4, + self::_encodeLength(strlen($RSAPrivateKey)), + $RSAPrivateKey + ); + $RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey); + if (!empty($password) || is_string($password)) { + $salt = Random::string(8); + $iterationCount = 2048; + + $crypto = new DES(DES::MODE_CBC); + $crypto->setPassword($password, 'pbkdf1', 'md5', $salt, $iterationCount); + $RSAPrivateKey = $crypto->encrypt($RSAPrivateKey); + + $parameters = pack( + 'Ca*a*Ca*N', + self::ASN1_OCTETSTRING, + self::_encodeLength(strlen($salt)), + $salt, + self::ASN1_INTEGER, + self::_encodeLength(4), + $iterationCount + ); + $pbeWithMD5AndDES_CBC = "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03"; + + $encryptionAlgorithm = pack( + 'Ca*a*Ca*a*', + self::ASN1_OBJECT, + self::_encodeLength(strlen($pbeWithMD5AndDES_CBC)), + $pbeWithMD5AndDES_CBC, + self::ASN1_SEQUENCE, + self::_encodeLength(strlen($parameters)), + $parameters + ); + + $RSAPrivateKey = pack( + 'Ca*a*Ca*a*', + self::ASN1_SEQUENCE, + self::_encodeLength(strlen($encryptionAlgorithm)), + $encryptionAlgorithm, + self::ASN1_OCTETSTRING, + self::_encodeLength(strlen($RSAPrivateKey)), + $RSAPrivateKey + ); + + $RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey); + + $RSAPrivateKey = "-----BEGIN ENCRYPTED PRIVATE KEY-----\r\n" . + chunk_split(Base64::encode($RSAPrivateKey), 64) . + '-----END ENCRYPTED PRIVATE KEY-----'; + } else { + $RSAPrivateKey = "-----BEGIN PRIVATE KEY-----\r\n" . + chunk_split(Base64::encode($RSAPrivateKey), 64) . + '-----END PRIVATE KEY-----'; + } + + return $RSAPrivateKey; + } + + /** + * Convert a public key to the appropriate format + * + * @access public + * @param \phpseclib\Math\BigInteger $n + * @param \phpseclib\Math\BigInteger $e + * @return string + */ + static function savePublicKey(BigInteger $n, BigInteger $e) + { + $modulus = $n->toBytes(true); + $publicExponent = $e->toBytes(true); + + // from : + // RSAPublicKey ::= SEQUENCE { + // modulus INTEGER, -- n + // publicExponent INTEGER -- e + // } + $components = array( + 'modulus' => pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($modulus)), $modulus), + 'publicExponent' => pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($publicExponent)), $publicExponent) + ); + + $RSAPublicKey = pack( + 'Ca*a*a*', + self::ASN1_SEQUENCE, + self::_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])), + $components['modulus'], + $components['publicExponent'] + ); + + // sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption. + $rsaOID = "\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00"; // hex version of MA0GCSqGSIb3DQEBAQUA + $RSAPublicKey = chr(0) . $RSAPublicKey; + $RSAPublicKey = chr(3) . self::_encodeLength(strlen($RSAPublicKey)) . $RSAPublicKey; + + $RSAPublicKey = pack( + 'Ca*a*', + self::ASN1_SEQUENCE, + self::_encodeLength(strlen($rsaOID . $RSAPublicKey)), + $rsaOID . $RSAPublicKey + ); + + $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" . + chunk_split(Base64::encode($RSAPublicKey), 64) . + '-----END PUBLIC KEY-----'; + + return $RSAPublicKey; + } +} diff --git a/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PuTTY.php b/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PuTTY.php new file mode 100644 index 0000000000..04c4ae20dc --- /dev/null +++ b/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PuTTY.php @@ -0,0 +1,313 @@ + + * @copyright 2015 Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net + */ + +namespace phpseclib\Crypt\RSA; + +use ParagonIE\ConstantTime\Base64; +use ParagonIE\ConstantTime\Hex; +use phpseclib\Crypt\AES; +use phpseclib\Crypt\Hash; +use phpseclib\Math\BigInteger; + +/** + * PuTTY Formatted RSA Key Handler + * + * @package RSA + * @author Jim Wigginton + * @access public + */ +class PuTTY +{ + /** + * Default comment + * + * @var string + * @access private + */ + static $comment = 'phpseclib-generated-key'; + + /** + * Sets the default comment + * + * @access public + * @param string $comment + */ + static function setComment($comment) + { + self::$comment = str_replace(array("\r", "\n"), '', $comment); + } + + /** + * Generate a symmetric key for PuTTY keys + * + * @access public + * @param string $password + * @param string $iv + * @param int $length + * @return string + */ + static function generateSymmetricKey($password, $length) + { + $symkey = ''; + $sequence = 0; + while (strlen($symkey) < $length) { + $temp = pack('Na*', $sequence++, $password); + $symkey.= Hex::decode(sha1($temp)); + } + return substr($symkey, 0, $length); + } + + /** + * Break a public or private key down into its constituent components + * + * @access public + * @param string $key + * @param string $password optional + * @return array + */ + static function load($key, $password = '') + { + if (!is_string($key)) { + return false; + } + + static $one; + if (!isset($one)) { + $one = new BigInteger(1); + } + + if (strpos($key, 'BEGIN SSH2 PUBLIC KEY')) { + $data = preg_split('#[\r\n]+#', $key); + $data = array_splice($data, 2, -1); + $data = implode('', $data); + + $components = OpenSSH::load($data); + if ($components === false) { + return false; + } + + if (!preg_match('#Comment: "(.+)"#', $key, $matches)) { + return false; + } + $components['comment'] = str_replace(array('\\\\', '\"'), array('\\', '"'), $matches[1]); + + return $components; + } + + $components = array('isPublicKey' => false); + $key = preg_split('#\r\n|\r|\n#', $key); + $type = trim(preg_replace('#PuTTY-User-Key-File-2: (.+)#', '$1', $key[0])); + if ($type != 'ssh-rsa') { + return false; + } + $encryption = trim(preg_replace('#Encryption: (.+)#', '$1', $key[1])); + $components['comment'] = trim(preg_replace('#Comment: (.+)#', '$1', $key[2])); + + $publicLength = trim(preg_replace('#Public-Lines: (\d+)#', '$1', $key[3])); + $public = Base64::decode(implode('', array_map('trim', array_slice($key, 4, $publicLength)))); + $public = substr($public, 11); + extract(unpack('Nlength', self::_string_shift($public, 4))); + $components['publicExponent'] = new BigInteger(self::_string_shift($public, $length), -256); + extract(unpack('Nlength', self::_string_shift($public, 4))); + $components['modulus'] = new BigInteger(self::_string_shift($public, $length), -256); + + $privateLength = trim(preg_replace('#Private-Lines: (\d+)#', '$1', $key[$publicLength + 4])); + $private = Base64::decode(implode('', array_map('trim', array_slice($key, $publicLength + 5, $privateLength)))); + + switch ($encryption) { + case 'aes256-cbc': + $symkey = static::generateSymmetricKey($password, 32); + $crypto = new AES(AES::MODE_CBC); + } + + if ($encryption != 'none') { + $crypto->setKey($symkey); + $crypto->setIV(str_repeat("\0", $crypto->getBlockLength() >> 3)); + $crypto->disablePadding(); + $private = $crypto->decrypt($private); + if ($private === false) { + return false; + } + } + + extract(unpack('Nlength', self::_string_shift($private, 4))); + if (strlen($private) < $length) { + return false; + } + $components['privateExponent'] = new BigInteger(self::_string_shift($private, $length), -256); + extract(unpack('Nlength', self::_string_shift($private, 4))); + if (strlen($private) < $length) { + return false; + } + $components['primes'] = array(1 => new BigInteger(self::_string_shift($private, $length), -256)); + extract(unpack('Nlength', self::_string_shift($private, 4))); + if (strlen($private) < $length) { + return false; + } + $components['primes'][] = new BigInteger(self::_string_shift($private, $length), -256); + + $temp = $components['primes'][1]->subtract($one); + $components['exponents'] = array(1 => $components['publicExponent']->modInverse($temp)); + $temp = $components['primes'][2]->subtract($one); + $components['exponents'][] = $components['publicExponent']->modInverse($temp); + + extract(unpack('Nlength', self::_string_shift($private, 4))); + if (strlen($private) < $length) { + return false; + } + $components['coefficients'] = array(2 => new BigInteger(self::_string_shift($private, $length), -256)); + + return $components; + } + + /** + * String Shift + * + * Inspired by array_shift + * + * @param string $string + * @param int $index + * @return string + * @access private + */ + static function _string_shift(&$string, $index = 1) + { + $substr = substr($string, 0, $index); + $string = substr($string, $index); + return $substr; + } + + /** + * Convert a private key to the appropriate format. + * + * @access public + * @param \phpseclib\Math\BigInteger $n + * @param \phpseclib\Math\BigInteger $e + * @param \phpseclib\Math\BigInteger $d + * @param array $primes + * @param array $exponents + * @param array $coefficients + * @param string $password optional + * @return string + */ + static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '') + { + if (count($primes) != 2) { + return false; + } + + $raw = array( + 'modulus' => $n->toBytes(true), + 'publicExponent' => $e->toBytes(true), + 'privateExponent' => $d->toBytes(true), + 'prime1' => $primes[1]->toBytes(true), + 'prime2' => $primes[2]->toBytes(true), + 'exponent1' => $exponents[1]->toBytes(true), + 'exponent2' => $exponents[2]->toBytes(true), + 'coefficient' => $coefficients[2]->toBytes(true) + ); + + $key = "PuTTY-User-Key-File-2: ssh-rsa\r\nEncryption: "; + $encryption = (!empty($password) || is_string($password)) ? 'aes256-cbc' : 'none'; + $key.= $encryption; + $key.= "\r\nComment: " . self::$comment . "\r\n"; + $public = pack( + 'Na*Na*Na*', + strlen('ssh-rsa'), + 'ssh-rsa', + strlen($raw['publicExponent']), + $raw['publicExponent'], + strlen($raw['modulus']), + $raw['modulus'] + ); + $source = pack( + 'Na*Na*Na*Na*', + strlen('ssh-rsa'), + 'ssh-rsa', + strlen($encryption), + $encryption, + strlen(self::$comment), + self::$comment, + strlen($public), + $public + ); + $public = Base64::encode($public); + $key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n"; + $key.= chunk_split($public, 64); + $private = pack( + 'Na*Na*Na*Na*', + strlen($raw['privateExponent']), + $raw['privateExponent'], + strlen($raw['prime1']), + $raw['prime1'], + strlen($raw['prime2']), + $raw['prime2'], + strlen($raw['coefficient']), + $raw['coefficient'] + ); + if (empty($password) && !is_string($password)) { + $source.= pack('Na*', strlen($private), $private); + $hashkey = 'putty-private-key-file-mac-key'; + } else { + $private.= Random::string(16 - (strlen($private) & 15)); + $source.= pack('Na*', strlen($private), $private); + $crypto = new AES(); + + $crypto->setKey(static::generateSymmetricKey($password, 32)); + $crypto->setIV(str_repeat("\0", $crypto->getBlockLength() >> 3)); + $crypto->disablePadding(); + $private = $crypto->encrypt($private); + $hashkey = 'putty-private-key-file-mac-key' . $password; + } + + $private = Base64::encode($private); + $key.= 'Private-Lines: ' . ((strlen($private) + 63) >> 6) . "\r\n"; + $key.= chunk_split($private, 64); + $hash = new Hash('sha1'); + $hash->setKey(sha1($hashkey, true)); + $key.= 'Private-MAC: ' . Hex::encode($hash->hash($source)) . "\r\n"; + + return $key; + } + + /** + * Convert a public key to the appropriate format + * + * @access public + * @param \phpseclib\Math\BigInteger $n + * @param \phpseclib\Math\BigInteger $e + * @return string + */ + static function savePublicKey(BigInteger $n, BigInteger $e) + { + $n = $n->toBytes(true); + $e = $e->toBytes(true); + + $key = pack( + 'Na*Na*Na*', + strlen('ssh-rsa'), + 'ssh-rsa', + strlen($e), + $e, + strlen($n), + $n + ); + $key = "---- BEGIN SSH2 PUBLIC KEY ----\r\n" . + 'Comment: "' . str_replace(array('\\', '"'), array('\\\\', '\"'), self::$comment) . "\"\r\n"; + chunk_split(Base64::encode($key), 64) . + '---- END SSH2 PUBLIC KEY ----'; + + return $key; + } +} diff --git a/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Raw.php b/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Raw.php new file mode 100644 index 0000000000..d399252163 --- /dev/null +++ b/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Raw.php @@ -0,0 +1,103 @@ + + * @copyright 2015 Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net + */ + +namespace phpseclib\Crypt\RSA; + +use phpseclib\Math\BigInteger; + +/** + * Raw RSA Key Handler + * + * @package RSA + * @author Jim Wigginton + * @access public + */ +class Raw +{ + /** + * Break a public or private key down into its constituent components + * + * @access public + * @param string $key + * @param string $password optional + * @return array + */ + static function load($key, $password = '') + { + if (!is_array($key)) { + return false; + } + if (isset($key['isPublicKey']) && isset($key['modulus'])) { + if (isset($key['privateExponent']) || isset($key['publicExponent'])) { + if (!isset($key['primes'])) { + return $key; + } + if (isset($key['exponents']) && isset($key['coefficients']) && isset($key['publicExponent']) && isset($key['privateExponent'])) { + return $key; + } + } + } + $components = array('isPublicKey' => true); + switch (true) { + case isset($key['e']): + $components['publicExponent'] = $key['e']; + break; + case isset($key['exponent']): + $components['publicExponent'] = $key['exponent']; + break; + case isset($key['publicExponent']): + $components['publicExponent'] = $key['publicExponent']; + break; + case isset($key[0]): + $components['publicExponent'] = $key[0]; + } + switch (true) { + case isset($key['n']): + $components['modulus'] = $key['n']; + break; + case isset($key['modulo']): + $components['modulus'] = $key['modulo']; + break; + case isset($key['modulus']): + $components['modulus'] = $key['modulus']; + break; + case isset($key[1]): + $components['modulus'] = $key[1]; + } + return isset($components['modulus']) && isset($components['publicExponent']) ? $components : false; + } + + /** + * Convert a public key to the appropriate format + * + * @access public + * @param \phpseclib\Math\BigInteger $n + * @param \phpseclib\Math\BigInteger $e + * @return string + */ + static function savePublicKey(BigInteger $n, BigInteger $e) + { + return array('e' => clone $e, 'n' => clone $n); + } +} diff --git a/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/XML.php b/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/XML.php new file mode 100644 index 0000000000..a257033b88 --- /dev/null +++ b/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/XML.php @@ -0,0 +1,147 @@ + + * @copyright 2015 Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net + */ + +namespace phpseclib\Crypt\RSA; + +use ParagonIE\ConstantTime\Base64; +use phpseclib\Math\BigInteger; + +/** + * XML Formatted RSA Key Handler + * + * @package RSA + * @author Jim Wigginton + * @access public + */ +class XML +{ + /** + * Break a public or private key down into its constituent components + * + * @access public + * @param string $key + * @param string $password optional + * @return array + */ + static function load($key, $password = '') + { + if (!is_string($key)) { + return false; + } + + $components = array( + 'isPublicKey' => false, + 'primes' => array(), + 'exponents' => array(), + 'coefficients' => array() + ); + + $use_errors = libxml_use_internal_errors(true); + + $dom = new \DOMDocument(); + if (!$dom->loadXML('' . $key . '')) { + return false; + } + $xpath = new \DOMXPath($dom); + $keys = array('modulus', 'exponent', 'p', 'q', 'dp', 'dq', 'inverseq', 'd'); + foreach ($keys as $key) { + // $dom->getElementsByTagName($key) is case-sensitive + $temp = $xpath->query("//*[translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='$key']"); + if (!$temp->length) { + continue; + } + $value = new BigInteger(Base64::decode($temp->item(0)->nodeValue), 256); + switch ($key) { + case 'modulus': + $components['modulus'] = $value; + break; + case 'exponent': + $components['publicExponent'] = $value; + break; + case 'p': + $components['primes'][1] = $value; + break; + case 'q': + $components['primes'][2] = $value; + break; + case 'dp': + $components['exponents'][1] = $value; + break; + case 'dq': + $components['exponents'][2] = $value; + break; + case 'inverseq': + $components['coefficients'][2] = $value; + break; + case 'd': + $components['privateExponent'] = $value; + } + } + + libxml_use_internal_errors($use_errors); + + return isset($components['modulus']) && isset($components['publicExponent']) ? $components : false; + } + + /** + * Convert a private key to the appropriate format. + * + * @access public + * @param \phpseclib\Math\BigInteger $n + * @param \phpseclib\Math\BigInteger $e + * @param \phpseclib\Math\BigInteger $d + * @param array $primes + * @param array $exponents + * @param array $coefficients + * @param string $password optional + * @return string + */ + static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '') + { + if (count($primes) != 2) { + return false; + } + return "\r\n" . + ' ' . Base64::encode($n->toBytes()) . "\r\n" . + ' ' . Base64::encode($e->toBytes()) . "\r\n" . + '

' . Base64::encode($primes[1]->toBytes()) . "

\r\n" . + ' ' . Base64::encode($primes[2]->toBytes()) . "\r\n" . + ' ' . Base64::encode($exponents[1]->toBytes()) . "\r\n" . + ' ' . Base64::encode($exponents[2]->toBytes()) . "\r\n" . + ' ' . Base64::encode($coefficients[2]->toBytes()) . "\r\n" . + ' ' . Base64::encode($d->toBytes()) . "\r\n" . + '
'; + } + + /** + * Convert a public key to the appropriate format + * + * @access public + * @param \phpseclib\Math\BigInteger $n + * @param \phpseclib\Math\BigInteger $e + * @return string + */ + static function savePublicKey(BigInteger $n, BigInteger $e) + { + return "\r\n" . + ' ' . Base64::encode($n->toBytes()) . "\r\n" . + ' ' . Base64::encode($e->toBytes()) . "\r\n" . + ''; + } +} diff --git a/vendor/phpseclib/phpseclib/phpseclib/Exception/BadConfigurationException.php b/vendor/phpseclib/phpseclib/phpseclib/Exception/BadConfigurationException.php new file mode 100644 index 0000000000..096148a0df --- /dev/null +++ b/vendor/phpseclib/phpseclib/phpseclib/Exception/BadConfigurationException.php @@ -0,0 +1,26 @@ + + * @copyright 2015 Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net + */ + +namespace phpseclib\Exception; + +/** + * BadConfigurationException + * + * @package BadConfigurationException + * @author Jim Wigginton + */ +class BadConfigurationException extends \RuntimeException +{ +} diff --git a/vendor/phpseclib/phpseclib/phpseclib/Exception/FileNotFoundException.php b/vendor/phpseclib/phpseclib/phpseclib/Exception/FileNotFoundException.php new file mode 100644 index 0000000000..984edfcc7a --- /dev/null +++ b/vendor/phpseclib/phpseclib/phpseclib/Exception/FileNotFoundException.php @@ -0,0 +1,26 @@ + + * @copyright 2015 Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net + */ + +namespace phpseclib\Exception; + +/** + * FileNotFoundException + * + * @package FileNotFoundException + * @author Jim Wigginton + */ +class FileNotFoundException extends \RuntimeException +{ +} diff --git a/vendor/phpseclib/phpseclib/phpseclib/Exception/NoSupportedAlgorithmsException.php b/vendor/phpseclib/phpseclib/phpseclib/Exception/NoSupportedAlgorithmsException.php new file mode 100644 index 0000000000..bca9a753b5 --- /dev/null +++ b/vendor/phpseclib/phpseclib/phpseclib/Exception/NoSupportedAlgorithmsException.php @@ -0,0 +1,26 @@ + + * @copyright 2015 Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net + */ + +namespace phpseclib\Exception; + +/** + * NoSupportedAlgorithmsException + * + * @package NoSupportedAlgorithmsException + * @author Jim Wigginton + */ +class NoSupportedAlgorithmsException extends \RuntimeException +{ +} diff --git a/vendor/phpseclib/phpseclib/phpseclib/Exception/UnsupportedAlgorithmException.php b/vendor/phpseclib/phpseclib/phpseclib/Exception/UnsupportedAlgorithmException.php new file mode 100644 index 0000000000..47cc41d4d3 --- /dev/null +++ b/vendor/phpseclib/phpseclib/phpseclib/Exception/UnsupportedAlgorithmException.php @@ -0,0 +1,26 @@ + + * @copyright 2015 Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net + */ + +namespace phpseclib\Exception; + +/** + * UnsupportedAlgorithmException + * + * @package UnsupportedAlgorithmException + * @author Jim Wigginton + */ +class UnsupportedAlgorithmException extends \RuntimeException +{ +}