diff --git a/.gitignore b/.gitignore
index 57872d0..ba3a105 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
/vendor/
+.composer.lock
diff --git a/.travis.yml b/.travis.yml
index dd6aaec..5197f82 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,11 +1,9 @@
language: php
php:
- - 5.3
- - 5.4
- - 5.5
- - 5.6
- - 7
+ - 8.1
+ - 8.2
+ - 8.3
- hhvm
cache:
@@ -22,8 +20,7 @@ before_script:
- composer install --dev --prefer-source
script:
- - ./vendor/bin/phpunit --coverage-clover=coverage.clover
- - ./vendor/bin/phpcs --standard=PSR2 src
+ - composer check
after_script:
- wget https://scrutinizer-ci.com/ocular.phar
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..5980ae0
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,18 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## 2.0.0
+
+### Breaking Changes
+
+- PHP 8.1 is now required
+- All class properties and function parameters are now typed
+- All functions now are properly return typed
+
+### Fixed
+
+- Fixed deprecation warnings of `Creation of dynamic property ... deprecated`
diff --git a/README.md b/README.md
index 23763dc..56b9f46 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,7 @@ without setting anything to get sane defaults.
build()
```
@@ -37,7 +37,7 @@ $client = Dflydev\Hawk\Client\ClientBuilder::create()
setCrypto($crypto)
->setTimeProvider($timeProvider)
->setNonceProvider($nonceProvider)
@@ -142,14 +142,14 @@ $isAuthenticatedResponse = $client->authenticate(
build();
// Create a Hawk request based on making a POST request to a specific URL
@@ -239,7 +239,7 @@ without setting anything but the credentials provider to get sane defaults.
$credentialsProvider = function ($id) {
if ('12345' === $id) {
- return new Dflydev\Hawk\Credentials\Credentials(
+ return new \Dflydev\Hawk\Credentials\Credentials(
'afe89a3x', // shared key
'sha256', // default: sha256
'12345' // identifier, default: null
@@ -248,7 +248,7 @@ $credentialsProvider = function ($id) {
};
// Simple example
-$server = Dflydev\Hawk\Server\ServerBuilder::create($credentialsProvider)
+$server = \Dflydev\Hawk\Server\ServerBuilder::create($credentialsProvider)
->build()
```
@@ -259,7 +259,7 @@ $server = Dflydev\Hawk\Server\ServerBuilder::create($credentialsProvider)
$credentialsProvider = function ($id) {
if ('12345' === $id) {
- return new Dflydev\Hawk\Credentials\Credentials(
+ return new \Dflydev\Hawk\Credentials\Credentials(
'afe89a3x', // shared key
'sha256', // default: sha256
'12345' // identifier, default: null
@@ -268,7 +268,7 @@ $credentialsProvider = function ($id) {
};
// A complete example
-$server = Dflydev\Hawk\Server\ServerBuilder::create($credentialsProvider)
+$server = \Dflydev\Hawk\Server\ServerBuilder::create($credentialsProvider)
->setCrypto($crypto)
->setTimeProvider($timeProvider)
->setNonceValidator($nonceValidator)
@@ -307,7 +307,7 @@ try {
'hello world!'
$authorization
);
-} catch(Dflydev\Hawk\Server\UnauthorizedException $e) {
+} catch(\Dflydev\Hawk\Server\UnauthorizedException $e) {
// If authorization is incorrect (invalid mac, etc.) we can catch an
// unauthorized exception.
throw $e;
@@ -367,7 +367,7 @@ header(sprintf("%s: %s", $header->fieldName(), $header->fieldValue()));
// Create a simple credentials provider
$credentialsProvider = function ($id) {
if ('12345' === $id) {
- return new Dflydev\Hawk\Credentials\Credentials(
+ return new \Dflydev\Hawk\Credentials\Credentials(
'afe89a3x', // shared key
'sha256', // default: sha256
'12345' // identifier, default: null
@@ -376,7 +376,7 @@ $credentialsProvider = function ($id) {
};
// Create a Hawk server
-$server = Dflydev\Hawk\Server\ServerBuilder::create($credentialsProvider)
+$server = \Dflydev\Hawk\Server\ServerBuilder::create($credentialsProvider)
->build()
// Get the authorization header for the request; it should be in the form
@@ -393,7 +393,7 @@ try {
'hello world!'
$authorization
);
-} catch(Dflydev\Hawk\Server\UnauthorizedException $e) {
+} catch(\Dflydev\Hawk\Server\UnauthorizedException $e) {
// If authorization is incorrect (invalid mac, etc.) we can catch an
// unauthorized exception.
throw $e;
@@ -487,7 +487,7 @@ A simple implementation of `CredentialsInterface`.
```php
=5.3.2"
- },
- "require-dev": {
- "mikey179/vfsstream": "1.1.*",
- "phpunit/phpunit": "3.7.*"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.1.x-dev"
- }
- },
- "autoload": {
- "psr-0": {
- "RandomLib": "lib"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Anthony Ferrara",
- "email": "ircmaxell@ircmaxell.com",
- "homepage": "http://blog.ircmaxell.com"
- }
- ],
- "description": "A Library For Generating Secure Random Numbers",
- "homepage": "https://github.com/ircmaxell/RandomLib",
- "keywords": [
- "cryptography",
- "random",
- "random-numbers",
- "random-strings"
- ],
- "time": "2015-04-08 13:58:58"
- },
- {
- "name": "ircmaxell/security-lib",
- "version": "v1.1.0",
- "source": {
- "type": "git",
- "url": "https://github.com/ircmaxell/SecurityLib.git",
- "reference": "f3db6de12c20c9bcd1aa3db4353a1bbe0e44e1b5"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/ircmaxell/SecurityLib/zipball/f3db6de12c20c9bcd1aa3db4353a1bbe0e44e1b5",
- "reference": "f3db6de12c20c9bcd1aa3db4353a1bbe0e44e1b5",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.2"
- },
- "require-dev": {
- "mikey179/vfsstream": "1.1.*"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0.x-dev"
- }
- },
- "autoload": {
- "psr-0": {
- "SecurityLib": "lib"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Anthony Ferrara",
- "email": "ircmaxell@ircmaxell.com",
- "homepage": "http://blog.ircmaxell.com"
- }
- ],
- "description": "A Base Security Library",
- "homepage": "https://github.com/ircmaxell/SecurityLib",
- "time": "2015-03-20 14:31:23"
- }
- ],
- "packages-dev": [
- {
- "name": "codeclimate/php-test-reporter",
- "version": "dev-master",
- "source": {
- "type": "git",
- "url": "https://github.com/codeclimate/php-test-reporter.git",
- "reference": "418ae782307841ac50fe26daa4cfe04520b0de9c"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/codeclimate/php-test-reporter/zipball/418ae782307841ac50fe26daa4cfe04520b0de9c",
- "reference": "418ae782307841ac50fe26daa4cfe04520b0de9c",
- "shasum": ""
- },
- "require": {
- "ext-curl": "*",
- "php": ">=5.3",
- "satooshi/php-coveralls": "0.6.*",
- "symfony/console": ">=2.0"
- },
- "require-dev": {
- "ext-xdebug": "*",
- "phpunit/phpunit": "3.7.*@stable"
- },
- "bin": [
- "composer/bin/test-reporter"
- ],
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "0.1.x-dev"
- }
- },
- "autoload": {
- "psr-0": {
- "CodeClimate\\Component": "src/",
- "CodeClimate\\Bundle": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Code Climate",
- "email": "hello@codeclimate.com",
- "homepage": "https://codeclimate.com"
- }
- ],
- "description": "PHP client for reporting test coverage to Code Climate",
- "homepage": "https://github.com/codeclimate/php-test-reporter",
- "keywords": [
- "codeclimate",
- "coverage"
- ],
- "time": "2015-04-18 14:43:54"
- },
- {
- "name": "doctrine/instantiator",
- "version": "1.0.4",
- "source": {
- "type": "git",
- "url": "https://github.com/doctrine/instantiator.git",
- "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f976e5de371104877ebc89bd8fecb0019ed9c119",
- "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119",
- "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.*@ALPHA"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0.x-dev"
- }
- },
- "autoload": {
- "psr-0": {
- "Doctrine\\Instantiator\\": "src"
- }
- },
- "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": "2014-10-13 12:58:55"
- },
- {
- "name": "guzzle/guzzle",
- "version": "v3.9.3",
- "source": {
- "type": "git",
- "url": "https://github.com/guzzle/guzzle3.git",
- "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9",
- "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9",
- "shasum": ""
- },
- "require": {
- "ext-curl": "*",
- "php": ">=5.3.3",
- "symfony/event-dispatcher": "~2.1"
- },
- "replace": {
- "guzzle/batch": "self.version",
- "guzzle/cache": "self.version",
- "guzzle/common": "self.version",
- "guzzle/http": "self.version",
- "guzzle/inflection": "self.version",
- "guzzle/iterator": "self.version",
- "guzzle/log": "self.version",
- "guzzle/parser": "self.version",
- "guzzle/plugin": "self.version",
- "guzzle/plugin-async": "self.version",
- "guzzle/plugin-backoff": "self.version",
- "guzzle/plugin-cache": "self.version",
- "guzzle/plugin-cookie": "self.version",
- "guzzle/plugin-curlauth": "self.version",
- "guzzle/plugin-error-response": "self.version",
- "guzzle/plugin-history": "self.version",
- "guzzle/plugin-log": "self.version",
- "guzzle/plugin-md5": "self.version",
- "guzzle/plugin-mock": "self.version",
- "guzzle/plugin-oauth": "self.version",
- "guzzle/service": "self.version",
- "guzzle/stream": "self.version"
- },
- "require-dev": {
- "doctrine/cache": "~1.3",
- "monolog/monolog": "~1.0",
- "phpunit/phpunit": "3.7.*",
- "psr/log": "~1.0",
- "symfony/class-loader": "~2.1",
- "zendframework/zend-cache": "2.*,<2.3",
- "zendframework/zend-log": "2.*,<2.3"
- },
- "suggest": {
- "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated."
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.9-dev"
- }
- },
- "autoload": {
- "psr-0": {
- "Guzzle": "src/",
- "Guzzle\\Tests": "tests/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Michael Dowling",
- "email": "mtdowling@gmail.com",
- "homepage": "https://github.com/mtdowling"
- },
- {
- "name": "Guzzle Community",
- "homepage": "https://github.com/guzzle/guzzle/contributors"
- }
- ],
- "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle",
- "homepage": "http://guzzlephp.org/",
- "keywords": [
- "client",
- "curl",
- "framework",
- "http",
- "http client",
- "rest",
- "web service"
- ],
- "time": "2015-03-18 18:23:50"
- },
- {
- "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": "1.4.0",
- "source": {
- "type": "git",
- "url": "https://github.com/phpspec/prophecy.git",
- "reference": "8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/phpspec/prophecy/zipball/8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5",
- "reference": "8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5",
- "shasum": ""
- },
- "require": {
- "doctrine/instantiator": "^1.0.2",
- "phpdocumentor/reflection-docblock": "~2.0",
- "sebastian/comparator": "~1.1"
- },
- "require-dev": {
- "phpspec/phpspec": "~2.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.4.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": "2015-03-27 19:31:25"
- },
- {
- "name": "phpunit/php-code-coverage",
- "version": "2.0.16",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/934fd03eb6840508231a7f73eb8940cf32c3b66c",
- "reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c",
- "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.0",
- "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.0.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-04-11 04:35:00"
- },
- {
- "name": "phpunit/php-file-iterator",
- "version": "1.4.0",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
- "reference": "a923bb15680d0089e2316f7a4af8f437046e96bb"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a923bb15680d0089e2316f7a4af8f437046e96bb",
- "reference": "a923bb15680d0089e2316f7a4af8f437046e96bb",
- "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-04-02 05:19:05"
- },
- {
- "name": "phpunit/php-text-template",
- "version": "1.2.0",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/php-text-template.git",
- "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a",
- "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "type": "library",
- "autoload": {
- "classmap": [
- "Text/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "include-path": [
- ""
- ],
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sb@sebastian-bergmann.de",
- "role": "lead"
- }
- ],
- "description": "Simple template engine.",
- "homepage": "https://github.com/sebastianbergmann/php-text-template/",
- "keywords": [
- "template"
- ],
- "time": "2014-01-30 17:20:04"
- },
- {
- "name": "phpunit/php-timer",
- "version": "1.0.5",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/php-timer.git",
- "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c",
- "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "type": "library",
- "autoload": {
- "classmap": [
- "PHP/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "include-path": [
- ""
- ],
- "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": "2013-08-02 07:42:54"
- },
- {
- "name": "phpunit/php-token-stream",
- "version": "1.4.1",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/php-token-stream.git",
- "reference": "eab81d02569310739373308137284e0158424330"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/eab81d02569310739373308137284e0158424330",
- "reference": "eab81d02569310739373308137284e0158424330",
- "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-04-08 04:46:07"
- },
- {
- "name": "phpunit/phpunit",
- "version": "4.6.4",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "163232991e652e6efed2f8470326fffa61e848e2"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/163232991e652e6efed2f8470326fffa61e848e2",
- "reference": "163232991e652e6efed2f8470326fffa61e848e2",
- "shasum": ""
- },
- "require": {
- "ext-dom": "*",
- "ext-json": "*",
- "ext-pcre": "*",
- "ext-reflection": "*",
- "ext-spl": "*",
- "php": ">=5.3.3",
- "phpspec/prophecy": "~1.3,>=1.3.1",
- "phpunit/php-code-coverage": "~2.0,>=2.0.11",
- "phpunit/php-file-iterator": "~1.4",
- "phpunit/php-text-template": "~1.2",
- "phpunit/php-timer": "~1.0",
- "phpunit/phpunit-mock-objects": "~2.3",
- "sebastian/comparator": "~1.1",
- "sebastian/diff": "~1.2",
- "sebastian/environment": "~1.2",
- "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.6.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": "2015-04-11 05:23:21"
- },
- {
- "name": "phpunit/phpunit-mock-objects",
- "version": "2.3.1",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
- "reference": "74ffb87f527f24616f72460e54b595f508dccb5c"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/74ffb87f527f24616f72460e54b595f508dccb5c",
- "reference": "74ffb87f527f24616f72460e54b595f508dccb5c",
- "shasum": ""
- },
- "require": {
- "doctrine/instantiator": "~1.0,>=1.0.2",
- "php": ">=5.3.3",
- "phpunit/php-text-template": "~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-04-02 05:36:41"
- },
- {
- "name": "psr/log",
- "version": "1.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/php-fig/log.git",
- "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b",
- "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b",
- "shasum": ""
- },
- "type": "library",
- "autoload": {
- "psr-0": {
- "Psr\\Log\\": ""
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "PHP-FIG",
- "homepage": "http://www.php-fig.org/"
- }
- ],
- "description": "Common interface for logging libraries",
- "keywords": [
- "log",
- "psr",
- "psr-3"
- ],
- "time": "2012-12-21 11:40:51"
- },
- {
- "name": "satooshi/php-coveralls",
- "version": "v0.6.1",
- "source": {
- "type": "git",
- "url": "https://github.com/satooshi/php-coveralls.git",
- "reference": "dd0df95bd37a7cf5c5c50304dfe260ffe4b50760"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/dd0df95bd37a7cf5c5c50304dfe260ffe4b50760",
- "reference": "dd0df95bd37a7cf5c5c50304dfe260ffe4b50760",
- "shasum": ""
- },
- "require": {
- "ext-curl": "*",
- "ext-json": "*",
- "ext-simplexml": "*",
- "guzzle/guzzle": ">=3.0",
- "php": ">=5.3",
- "psr/log": "1.0.0",
- "symfony/config": ">=2.0",
- "symfony/console": ">=2.0",
- "symfony/stopwatch": ">=2.2",
- "symfony/yaml": ">=2.0"
- },
- "require-dev": {
- "apigen/apigen": "2.8.*@stable",
- "pdepend/pdepend": "dev-master",
- "phpmd/phpmd": "dev-master",
- "phpunit/php-invoker": ">=1.1.0,<1.2.0",
- "phpunit/phpunit": "3.7.*@stable",
- "sebastian/finder-facade": "dev-master",
- "sebastian/phpcpd": "1.4.*@stable",
- "squizlabs/php_codesniffer": "1.4.*@stable",
- "theseer/fdomdocument": "dev-master"
- },
- "bin": [
- "composer/bin/coveralls"
- ],
- "type": "library",
- "autoload": {
- "psr-0": {
- "Contrib\\Component": "src/",
- "Contrib\\Bundle": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Kitamura Satoshi",
- "email": "with.no.parachute@gmail.com",
- "homepage": "https://www.facebook.com/satooshi.jp"
- }
- ],
- "description": "PHP client library for Coveralls API",
- "homepage": "https://github.com/satooshi/php-coveralls",
- "keywords": [
- "ci",
- "coverage",
- "github",
- "test"
- ],
- "time": "2013-05-04 08:07:33"
- },
- {
- "name": "sebastian/comparator",
- "version": "1.1.1",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "1dd8869519a225f7f2b9eb663e225298fade819e"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dd8869519a225f7f2b9eb663e225298fade819e",
- "reference": "1dd8869519a225f7f2b9eb663e225298fade819e",
- "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.1.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-01-29 16:28:08"
- },
- {
- "name": "sebastian/diff",
- "version": "1.3.0",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/diff.git",
- "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3",
- "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "require-dev": {
- "phpunit/phpunit": "~4.2"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.3-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": "http://www.github.com/sebastianbergmann/diff",
- "keywords": [
- "diff"
- ],
- "time": "2015-02-22 15:13:53"
- },
- {
- "name": "sebastian/environment",
- "version": "1.2.2",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/environment.git",
- "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5a8c7d31914337b69923db26c4221b81ff5a196e",
- "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e",
- "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": "2015-01-01 10:01:08"
- },
- {
- "name": "sebastian/exporter",
- "version": "1.2.0",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/exporter.git",
- "reference": "84839970d05254c73cde183a721c7af13aede943"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/84839970d05254c73cde183a721c7af13aede943",
- "reference": "84839970d05254c73cde183a721c7af13aede943",
- "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-01-27 07:23:06"
- },
- {
- "name": "sebastian/global-state",
- "version": "1.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/global-state.git",
- "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/c7428acdb62ece0a45e6306f1ae85e1c05b09c01",
- "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01",
- "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": "2014-10-06 09:23:50"
- },
- {
- "name": "sebastian/recursion-context",
- "version": "1.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/recursion-context.git",
- "reference": "3989662bbb30a29d20d9faa04a846af79b276252"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/3989662bbb30a29d20d9faa04a846af79b276252",
- "reference": "3989662bbb30a29d20d9faa04a846af79b276252",
- "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-01-24 09:48:32"
- },
- {
- "name": "sebastian/version",
- "version": "1.0.5",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/version.git",
- "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ab931d46cd0d3204a91e1b9a40c4bc13032b58e4",
- "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4",
- "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-02-24 06:35:25"
- },
- {
- "name": "squizlabs/php_codesniffer",
- "version": "2.3.1",
- "source": {
- "type": "git",
- "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
- "reference": "f3100143e94bbeeaa4f1cd7c6389c3733d3d1ce1"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/f3100143e94bbeeaa4f1cd7c6389c3733d3d1ce1",
- "reference": "f3100143e94bbeeaa4f1cd7c6389c3733d3d1ce1",
- "shasum": ""
- },
- "require": {
- "ext-tokenizer": "*",
- "ext-xmlwriter": "*",
- "php": ">=5.1.2"
- },
- "bin": [
- "scripts/phpcs",
- "scripts/phpcbf"
- ],
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.0.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": "2015-04-23 03:40:59"
- },
- {
- "name": "symfony/config",
- "version": "v2.6.6",
- "target-dir": "Symfony/Component/Config",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/Config.git",
- "reference": "d91be01336605db8da21b79bc771e46a7276d1bc"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/Config/zipball/d91be01336605db8da21b79bc771e46a7276d1bc",
- "reference": "d91be01336605db8da21b79bc771e46a7276d1bc",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3",
- "symfony/filesystem": "~2.3"
- },
- "require-dev": {
- "symfony/phpunit-bridge": "~2.7"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.6-dev"
- }
- },
- "autoload": {
- "psr-0": {
- "Symfony\\Component\\Config\\": ""
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Symfony Community",
- "homepage": "http://symfony.com/contributors"
- },
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- }
- ],
- "description": "Symfony Config Component",
- "homepage": "http://symfony.com",
- "time": "2015-03-30 15:54:10"
- },
- {
- "name": "symfony/console",
- "version": "v2.6.6",
- "target-dir": "Symfony/Component/Console",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/Console.git",
- "reference": "5b91dc4ed5eb08553f57f6df04c4730a73992667"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/Console/zipball/5b91dc4ed5eb08553f57f6df04c4730a73992667",
- "reference": "5b91dc4ed5eb08553f57f6df04c4730a73992667",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "require-dev": {
- "psr/log": "~1.0",
- "symfony/event-dispatcher": "~2.1",
- "symfony/phpunit-bridge": "~2.7",
- "symfony/process": "~2.1"
- },
- "suggest": {
- "psr/log": "For using the console logger",
- "symfony/event-dispatcher": "",
- "symfony/process": ""
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.6-dev"
- }
- },
- "autoload": {
- "psr-0": {
- "Symfony\\Component\\Console\\": ""
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Symfony Community",
- "homepage": "http://symfony.com/contributors"
- },
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- }
- ],
- "description": "Symfony Console Component",
- "homepage": "http://symfony.com",
- "time": "2015-03-30 15:54:10"
- },
- {
- "name": "symfony/event-dispatcher",
- "version": "v2.6.6",
- "target-dir": "Symfony/Component/EventDispatcher",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/EventDispatcher.git",
- "reference": "70f7c8478739ad21e3deef0d977b38c77f1fb284"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/70f7c8478739ad21e3deef0d977b38c77f1fb284",
- "reference": "70f7c8478739ad21e3deef0d977b38c77f1fb284",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "require-dev": {
- "psr/log": "~1.0",
- "symfony/config": "~2.0,>=2.0.5",
- "symfony/dependency-injection": "~2.6",
- "symfony/expression-language": "~2.6",
- "symfony/phpunit-bridge": "~2.7",
- "symfony/stopwatch": "~2.3"
- },
- "suggest": {
- "symfony/dependency-injection": "",
- "symfony/http-kernel": ""
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.6-dev"
- }
- },
- "autoload": {
- "psr-0": {
- "Symfony\\Component\\EventDispatcher\\": ""
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Symfony Community",
- "homepage": "http://symfony.com/contributors"
- },
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- }
- ],
- "description": "Symfony EventDispatcher Component",
- "homepage": "http://symfony.com",
- "time": "2015-03-13 17:37:22"
- },
- {
- "name": "symfony/filesystem",
- "version": "v2.6.6",
- "target-dir": "Symfony/Component/Filesystem",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/Filesystem.git",
- "reference": "4983964b3693e4f13449cb3800c64a9112c301b4"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/Filesystem/zipball/4983964b3693e4f13449cb3800c64a9112c301b4",
- "reference": "4983964b3693e4f13449cb3800c64a9112c301b4",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "require-dev": {
- "symfony/phpunit-bridge": "~2.7"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.6-dev"
- }
- },
- "autoload": {
- "psr-0": {
- "Symfony\\Component\\Filesystem\\": ""
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Symfony Community",
- "homepage": "http://symfony.com/contributors"
- },
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- }
- ],
- "description": "Symfony Filesystem Component",
- "homepage": "http://symfony.com",
- "time": "2015-03-22 16:55:57"
- },
- {
- "name": "symfony/stopwatch",
- "version": "v2.6.6",
- "target-dir": "Symfony/Component/Stopwatch",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/Stopwatch.git",
- "reference": "5f196e84b5640424a166d2ce9cca161ce1e9d912"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/5f196e84b5640424a166d2ce9cca161ce1e9d912",
- "reference": "5f196e84b5640424a166d2ce9cca161ce1e9d912",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "require-dev": {
- "symfony/phpunit-bridge": "~2.7"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.6-dev"
- }
- },
- "autoload": {
- "psr-0": {
- "Symfony\\Component\\Stopwatch\\": ""
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Symfony Community",
- "homepage": "http://symfony.com/contributors"
- },
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- }
- ],
- "description": "Symfony Stopwatch Component",
- "homepage": "http://symfony.com",
- "time": "2015-03-22 16:55:57"
- },
- {
- "name": "symfony/yaml",
- "version": "v2.6.6",
- "target-dir": "Symfony/Component/Yaml",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/Yaml.git",
- "reference": "174f009ed36379a801109955fc5a71a49fe62dd4"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/Yaml/zipball/174f009ed36379a801109955fc5a71a49fe62dd4",
- "reference": "174f009ed36379a801109955fc5a71a49fe62dd4",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "require-dev": {
- "symfony/phpunit-bridge": "~2.7"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.6-dev"
- }
- },
- "autoload": {
- "psr-0": {
- "Symfony\\Component\\Yaml\\": ""
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Symfony Community",
- "homepage": "http://symfony.com/contributors"
- },
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- }
- ],
- "description": "Symfony Yaml Component",
- "homepage": "http://symfony.com",
- "time": "2015-03-30 15:54:10"
- }
- ],
- "aliases": [],
- "minimum-stability": "stable",
- "stability-flags": {
- "ircmaxell/random-lib": 20,
- "codeclimate/php-test-reporter": 20
- },
- "prefer-stable": false,
- "prefer-lowest": false,
- "platform": [],
- "platform-dev": []
-}
diff --git a/data/.gitignore b/data/.gitignore
new file mode 100644
index 0000000..c96a04f
--- /dev/null
+++ b/data/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
\ No newline at end of file
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
new file mode 100644
index 0000000..55bae07
--- /dev/null
+++ b/phpcs.xml.dist
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+ src
+ tests
+
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
new file mode 100644
index 0000000..51ee5ab
--- /dev/null
+++ b/phpstan-baseline.neon
@@ -0,0 +1,11 @@
+parameters:
+ ignoreErrors:
+ -
+ message: "#^Unsafe usage of new static\\(\\)\\.$#"
+ count: 1
+ path: src/Client/ClientBuilder.php
+
+ -
+ message: "#^Unsafe usage of new static\\(\\)\\.$#"
+ count: 1
+ path: src/Server/ServerBuilder.php
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
new file mode 100644
index 0000000..810a3c2
--- /dev/null
+++ b/phpstan.neon.dist
@@ -0,0 +1,16 @@
+includes:
+ - phpstan-baseline.neon
+ - vendor/phpstan/phpstan-phpunit/extension.neon
+ - vendor/phpstan/phpstan-phpunit/rules.neon
+ - vendor/phpstan/phpstan-deprecation-rules/rules.neon
+
+parameters:
+ tmpDir: data/phpstan
+ cache:
+ nodesByStringCountMax: 0
+ level: 8
+ fileExtensions:
+ - php
+ paths:
+ - src
+ - tests
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index a2437ec..1f44878 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,30 +1,20 @@
-
-
+
- ./tests/unit/
-
-
-
-
-
- ./tests/integration/
-
-
-
-
-
- ./tests/functional/
+ ./tests/unit
-
-
-
- ./src/
-
-
+
+
+ ./src
+
+
diff --git a/rector.config.php b/rector.config.php
new file mode 100644
index 0000000..93eec1f
--- /dev/null
+++ b/rector.config.php
@@ -0,0 +1,34 @@
+paths(
+ [
+ __DIR__ . '/src',
+ __DIR__ . '/tests',
+ ]
+ );
+
+ $rectorConfig->sets(
+ [
+ PHPUnitSetList::PHPUNIT_100,
+ PHPUnitSetList::PHPUNIT_CODE_QUALITY,
+ LevelSetList::UP_TO_PHP_81,
+ DowngradeLevelSetList::DOWN_TO_PHP_81,
+ SetList::CODE_QUALITY,
+ SetList::TYPE_DECLARATION,
+ ]
+ );
+
+ $rectorConfig->importNames();
+};
diff --git a/src/Dflydev/Hawk/Client/Client.php b/src/Client/Client.php
similarity index 67%
rename from src/Dflydev/Hawk/Client/Client.php
rename to src/Client/Client.php
index c085abf..395bebb 100644
--- a/src/Dflydev/Hawk/Client/Client.php
+++ b/src/Client/Client.php
@@ -5,51 +5,47 @@
use Dflydev\Hawk\Credentials\CredentialsInterface;
use Dflydev\Hawk\Crypto\Artifacts;
use Dflydev\Hawk\Crypto\Crypto;
-use Dflydev\Hawk\Header\Header;
use Dflydev\Hawk\Header\HeaderFactory;
use Dflydev\Hawk\Nonce\NonceProviderInterface;
use Dflydev\Hawk\Time\TimeProviderInterface;
+use InvalidArgumentException;
class Client implements ClientInterface
{
- private $crypto;
- private $timeProvider;
- private $nonceProvider;
- private $localtimeOffset;
-
/**
* @param integer $localtimeOffset
*/
public function __construct(
- Crypto $crypto,
- TimeProviderInterface $timeProvider,
- NonceProviderInterface $nonceProvider,
- $localtimeOffset
+ private readonly Crypto $crypto,
+ private readonly TimeProviderInterface $timeProvider,
+ private readonly NonceProviderInterface $nonceProvider,
+ private int $localtimeOffset
) {
- $this->crypto = $crypto;
- $this->timeProvider = $timeProvider;
- $this->nonceProvider = $nonceProvider;
- $this->localtimeOffset = $localtimeOffset;
}
- public function createRequest(CredentialsInterface $credentials, $uri, $method, array $options = array())
- {
- $timestamp = isset($options['timestamp']) ? $options['timestamp'] : $this->timeProvider->createTimestamp();
+ public function createRequest(
+ CredentialsInterface $credentials,
+ string $uri,
+ string $method,
+ array $options = []
+ ): Request {
+ $timestamp = $options['timestamp'] ?? $this->timeProvider->createTimestamp();
if ($this->localtimeOffset) {
$timestamp += $this->localtimeOffset;
}
+ /** @var array{host: string, path?: string, query?: string, scheme: string, port?: int} $parsed */
$parsed = parse_url($uri);
$host = $parsed['host'];
- $resource = isset($parsed['path']) ? $parsed['path'] : '';
+ $resource = $parsed['path'] ?? '';
if (isset($parsed['query'])) {
- $resource .= '?'.$parsed['query'];
+ $resource .= '?' . $parsed['query'];
}
- $port = isset($parsed['port']) ? $parsed['port'] : ($parsed['scheme'] === 'https' ? 443 : 80);
+ $port = $parsed['port'] ?? ($parsed['scheme'] === 'https' ? 443 : 80);
- $nonce = isset($options['nonce']) ? $options['nonce'] : $this->nonceProvider->createNonce();
+ $nonce = $options['nonce'] ?? $this->nonceProvider->createNonce();
if (isset($options['payload']) || isset($options['content_type'])) {
if (isset($options['payload']) && isset($options['content_type'])) {
@@ -57,7 +53,7 @@ public function createRequest(CredentialsInterface $credentials, $uri, $method,
$contentType = $options['content_type'];
$hash = $this->crypto->calculatePayloadHash($payload, $credentials->algorithm(), $contentType);
} else {
- throw new \InvalidArgumentException(
+ throw new InvalidArgumentException(
"If one of 'payload' and 'content_type' are specified, both must be specified."
);
}
@@ -67,9 +63,9 @@ public function createRequest(CredentialsInterface $credentials, $uri, $method,
$hash = null;
}
- $ext = isset($options['ext']) ? $options['ext'] : null;
- $app = isset($options['app']) ? $options['app'] : null;
- $dlg = isset($options['dlg']) ? $options['dlg'] : null;
+ $ext = $options['ext'] ?? null;
+ $app = $options['app'] ?? null;
+ $dlg = $options['dlg'] ?? null;
$artifacts = new Artifacts(
$method,
@@ -86,11 +82,7 @@ public function createRequest(CredentialsInterface $credentials, $uri, $method,
$dlg
);
- $attributes = array(
- 'id' => $credentials->id(),
- 'ts' => $artifacts->timestamp(),
- 'nonce' => $artifacts->nonce(),
- );
+ $attributes = ['id' => $credentials->id(), 'ts' => $artifacts->timestamp(), 'nonce' => $artifacts->nonce()];
if (null !== $hash) {
$attributes['hash'] = $hash;
@@ -116,14 +108,14 @@ public function createRequest(CredentialsInterface $credentials, $uri, $method,
public function authenticate(
CredentialsInterface $credentials,
Request $request,
- $headerObjectOrString,
- array $options = array()
- ) {
+ mixed $headerObjectOrString,
+ array $options = []
+ ): bool {
$header = HeaderFactory::createFromHeaderObjectOrString(
'Server-Authorization',
$headerObjectOrString,
- function () {
- throw new \InvalidArgumentException(
+ function (): never {
+ throw new InvalidArgumentException(
'Header must either be a string or an instance of "Dflydev\Hawk\Header\Header"'
);
}
@@ -134,7 +126,7 @@ function () {
$payload = $options['payload'];
$contentType = $options['content_type'];
} else {
- throw new \InvalidArgumentException(
+ throw new InvalidArgumentException(
'If one of "payload" and "content_type" are specified, both must be specified.'
);
}
@@ -179,24 +171,39 @@ function () {
return $artifacts->hash() === $hash;
}
- public function createBewit(CredentialsInterface $credentials, $uri, $ttlSec, array $options = array())
- {
- $timestamp = isset($options['timestamp']) ? $options['timestamp'] : $this->timeProvider->createTimestamp();
+ /**
+ * @param CredentialsInterface $credentials
+ * @param string $uri
+ * @param int $ttlSec
+ * @param array{
+ * timestamp?: int,
+ * ext?: string,
+ * } $options
+ * @return string
+ */
+ public function createBewit(
+ CredentialsInterface $credentials,
+ string $uri,
+ int $ttlSec,
+ array $options = []
+ ): string {
+ $timestamp = $options['timestamp'] ?? $this->timeProvider->createTimestamp();
if ($this->localtimeOffset) {
$timestamp += $this->localtimeOffset;
}
+ /** @var array{host: string, path?: string, query?: string, scheme: string, port?: int} $parsed */
$parsed = parse_url($uri);
$host = $parsed['host'];
- $resource = isset($parsed['path']) ? $parsed['path'] : '';
+ $resource = $parsed['path'] ?? '';
if (isset($parsed['query'])) {
- $resource .= '?'.$parsed['query'];
+ $resource .= '?' . $parsed['query'];
}
- $port = isset($parsed['port']) ? $parsed['port'] : ($parsed['scheme'] === 'https' ? 443 : 80);
+ $port = $parsed['port'] ?? ($parsed['scheme'] === 'https' ? 443 : 80);
- $ext = isset($options['ext']) ? $options['ext'] : null;
+ $ext = $options['ext'] ?? null;
$exp = $timestamp + $ttlSec;
@@ -210,16 +217,16 @@ public function createBewit(CredentialsInterface $credentials, $uri, $ttlSec, ar
$ext
);
- $bewit = implode('\\', array(
+ $bewit = implode('\\', [
$credentials->id(),
$exp,
$this->crypto->calculateMac('bewit', $credentials, $artifacts),
- $ext,
- ));
+ $ext
+ ]);
return str_replace(
- array('+', '/', '=', "\n"),
- array('-', '_', '', ''),
+ ['+', '/', '=', "\n"],
+ ['-', '_', '', ''],
base64_encode($bewit)
);
}
diff --git a/src/Dflydev/Hawk/Client/ClientBuilder.php b/src/Client/ClientBuilder.php
similarity index 68%
rename from src/Dflydev/Hawk/Client/ClientBuilder.php
rename to src/Client/ClientBuilder.php
index 82129a9..e21691a 100644
--- a/src/Dflydev/Hawk/Client/ClientBuilder.php
+++ b/src/Client/ClientBuilder.php
@@ -10,42 +10,42 @@
class ClientBuilder
{
- private $crypto;
- private $timeProvider;
- private $nonceProvider;
- private $localtimeOffset = 0;
+ private ?Crypto $crypto = null;
+ private ?TimeProviderInterface $timeProvider = null;
+ private ?NonceProviderInterface $nonceProvider = null;
+ private int $localtimeOffset = 0;
- public function setCrypto(Crypto $crypto)
+ public function setCrypto(Crypto $crypto): static
{
$this->crypto = $crypto;
return $this;
}
- public function setTimeProvider(TimeProviderInterface $timeProvider)
+ public function setTimeProvider(TimeProviderInterface $timeProvider): static
{
$this->timeProvider = $timeProvider;
return $this;
}
- public function setNonceProvider(NonceProviderInterface $nonceProvider)
+ public function setNonceProvider(NonceProviderInterface $nonceProvider): static
{
$this->nonceProvider = $nonceProvider;
return $this;
}
- public function setLocaltimeOffset($localtimeOffset = null)
+ public function setLocaltimeOffset(int $localtimeOffset): static
{
$this->localtimeOffset = $localtimeOffset;
return $this;
}
- public function build()
+ public function build(): Client
{
- $crypto = $this->crypto ?: new Crypto;
+ $crypto = $this->crypto ?: new Crypto();
$timeProvider = $this->timeProvider ?: DefaultTimeProviderFactory::create();
$nonceProvider = $this->nonceProvider ?: DefaultNonceProviderFactory::create();
@@ -57,8 +57,8 @@ public function build()
);
}
- public static function create()
+ public static function create(): static
{
- return new static;
+ return new static();
}
}
diff --git a/src/Client/ClientInterface.php b/src/Client/ClientInterface.php
new file mode 100644
index 0000000..8132af6
--- /dev/null
+++ b/src/Client/ClientInterface.php
@@ -0,0 +1,43 @@
+header;
+ }
+
+ public function artifacts(): Artifacts
+ {
+ return $this->artifacts;
+ }
+}
diff --git a/src/Credentials/CallbackCredentialsProvider.php b/src/Credentials/CallbackCredentialsProvider.php
new file mode 100644
index 0000000..cdf4231
--- /dev/null
+++ b/src/Credentials/CallbackCredentialsProvider.php
@@ -0,0 +1,18 @@
+callback, $id);
+ }
+}
diff --git a/src/Credentials/Credentials.php b/src/Credentials/Credentials.php
new file mode 100644
index 0000000..b4708c5
--- /dev/null
+++ b/src/Credentials/Credentials.php
@@ -0,0 +1,25 @@
+id;
+ }
+
+ public function key(): string
+ {
+ return $this->key;
+ }
+
+ public function algorithm(): string
+ {
+ return $this->algorithm;
+ }
+}
diff --git a/src/Credentials/CredentialsInterface.php b/src/Credentials/CredentialsInterface.php
new file mode 100644
index 0000000..5e7000c
--- /dev/null
+++ b/src/Credentials/CredentialsInterface.php
@@ -0,0 +1,10 @@
+timestamp;
+ }
+
+ public function nonce(): string
+ {
+ return $this->nonce;
+ }
+
+ public function ext(): ?string
+ {
+ return $this->ext;
+ }
+
+ public function payload(): mixed
+ {
+ return $this->payload;
+ }
+
+ public function contentType(): ?string
+ {
+ return $this->contentType;
+ }
+
+ public function hash(): ?string
+ {
+ return $this->hash;
+ }
+
+ public function app(): ?string
+ {
+ return $this->app;
+ }
+
+ public function dlg(): ?string
+ {
+ return $this->dlg;
+ }
+
+ public function resource(): mixed
+ {
+ return $this->resource;
+ }
+
+ public function host(): string
+ {
+ return $this->host;
+ }
+
+ public function port(): int
+ {
+ return $this->port;
+ }
+
+ public function method(): string
+ {
+ return $this->method;
+ }
+}
diff --git a/src/Crypto/Crypto.php b/src/Crypto/Crypto.php
new file mode 100644
index 0000000..d156c7e
--- /dev/null
+++ b/src/Crypto/Crypto.php
@@ -0,0 +1,94 @@
+generateNormalizedString($type, $attributes);
+
+ return base64_encode(
+ hash_hmac(
+ $credentials->algorithm(),
+ $normalized,
+ $credentials->key(),
+ true
+ )
+ );
+ }
+
+ public function calculateTsMac(int $timestamp, CredentialsInterface $credentials): string
+ {
+ $normalized = 'hawk.' . self::HEADER_VERSION . '.ts' . "\n" .
+ $timestamp . "\n";
+
+ return base64_encode(hash_hmac(
+ $credentials->algorithm(),
+ $normalized,
+ $credentials->key(),
+ true
+ ));
+ }
+
+ public function fixedTimeComparison(string $a, string $b): bool
+ {
+ $mismatch = strlen($a) === strlen($b) ? 0 : 1;
+ if ($mismatch !== 0) {
+ $b = $a;
+ }
+
+ for ($i = 0; $i < strlen($a); $i++) {
+ $ac = $a[$i];
+ $bc = $b[$i];
+ $mismatch += $ac === $bc ? 0 : 1;
+ }
+
+ return (0 === $mismatch);
+ }
+
+ private function generateNormalizedString(string $type, Artifacts $attributes): string
+ {
+ $normalized = 'hawk.' . self::HEADER_VERSION . '.' . $type . "\n" .
+ $attributes->timestamp() . "\n" .
+ $attributes->nonce() . "\n" .
+ strtoupper((string) $attributes->method()) . "\n" .
+ $attributes->resource() . "\n" .
+ strtolower((string) $attributes->host()) . "\n" .
+ $attributes->port() . "\n" .
+ $attributes->hash() . "\n";
+
+ if ($attributes->ext()) {
+ // TODO: escape ext
+ $normalized .= $attributes->ext();
+ }
+
+ $normalized .= "\n";
+
+ if ($attributes->app()) {
+ $normalized .= $attributes->app() . "\n" .
+ $attributes->dlg() . "\n";
+ }
+
+ return $normalized;
+ }
+}
diff --git a/src/Dflydev/Hawk/Client/ClientInterface.php b/src/Dflydev/Hawk/Client/ClientInterface.php
deleted file mode 100644
index 8fe0368..0000000
--- a/src/Dflydev/Hawk/Client/ClientInterface.php
+++ /dev/null
@@ -1,16 +0,0 @@
-header = $header;
- $this->artifacts = $artifacts;
- }
-
- public function header()
- {
- return $this->header;
- }
-
- public function artifacts()
- {
- return $this->artifacts;
- }
-}
diff --git a/src/Dflydev/Hawk/Credentials/CallbackCredentialsProvider.php b/src/Dflydev/Hawk/Credentials/CallbackCredentialsProvider.php
deleted file mode 100644
index a95eaab..0000000
--- a/src/Dflydev/Hawk/Credentials/CallbackCredentialsProvider.php
+++ /dev/null
@@ -1,18 +0,0 @@
-callback = $callback;
- }
-
- public function loadCredentialsById($id)
- {
- return call_user_func($this->callback, $id);
- }
-}
diff --git a/src/Dflydev/Hawk/Credentials/Credentials.php b/src/Dflydev/Hawk/Credentials/Credentials.php
deleted file mode 100644
index b8fa9be..0000000
--- a/src/Dflydev/Hawk/Credentials/Credentials.php
+++ /dev/null
@@ -1,32 +0,0 @@
-key = $key;
- $this->algorithm = $algorithm;
- $this->id = $id;
- }
-
- public function id()
- {
- return $this->id;
- }
-
- public function key()
- {
- return $this->key;
- }
-
- public function algorithm()
- {
- return $this->algorithm;
- }
-}
diff --git a/src/Dflydev/Hawk/Credentials/CredentialsInterface.php b/src/Dflydev/Hawk/Credentials/CredentialsInterface.php
deleted file mode 100644
index a32fe52..0000000
--- a/src/Dflydev/Hawk/Credentials/CredentialsInterface.php
+++ /dev/null
@@ -1,10 +0,0 @@
-method = $method;
- $this->host = $host;
- $this->port = $port;
- $this->resource = $resource;
- $this->timestamp = $timestamp;
- $this->nonce = $nonce;
- $this->ext = $ext;
- $this->payload = $payload;
- $this->contentType = $contentType;
- $this->hash = $hash;
- $this->app = $app;
- $this->dlg = $dlg;
- }
-
- public function timestamp()
- {
- return $this->timestamp;
- }
-
- public function nonce()
- {
- return $this->nonce;
- }
-
- public function ext()
- {
- return $this->ext;
- }
-
- public function payload()
- {
- return $this->payload;
- }
-
- public function contentType()
- {
- return $this->contentType;
- }
-
- public function hash()
- {
- return $this->hash;
- }
-
- public function app()
- {
- return $this->app;
- }
-
- public function dlg()
- {
- return $this->dlg;
- }
-
- public function resource()
- {
- return $this->resource;
- }
-
- public function host()
- {
- return $this->host;
- }
-
- public function port()
- {
- return $this->port;
- }
-
- public function method()
- {
- return $this->method;
- }
-}
diff --git a/src/Dflydev/Hawk/Crypto/Crypto.php b/src/Dflydev/Hawk/Crypto/Crypto.php
deleted file mode 100644
index 1fa4f32..0000000
--- a/src/Dflydev/Hawk/Crypto/Crypto.php
+++ /dev/null
@@ -1,84 +0,0 @@
-generateNormalizedString($type, $attributes);
-
- return base64_encode(hash_hmac($credentials->algorithm(), $normalized, $credentials->key(), true));
- }
-
- public function calculateTsMac($ts, CredentialsInterface $credentials)
- {
- $normalized = 'hawk.'.self::HEADER_VERSION.'.ts'."\n".
- $ts."\n";
-
- return base64_encode(hash_hmac(
- $credentials->algorithm(),
- $normalized,
- $credentials->key(),
- true
- ));
- }
-
- public function fixedTimeComparison($a, $b)
- {
- $mismatch = strlen($a) === strlen($b) ? 0 : 1;
- if ($mismatch) {
- $b = $a;
- }
-
- for ($i = 0; $i < strlen($a); $i++) {
- $ac = $a[$i];
- $bc = $b[$i];
- $mismatch += $ac === $bc ? 0 : 1;
- }
-
- return (0 === $mismatch);
- }
-
- private function generateNormalizedString($type, Artifacts $attributes)
- {
- $normalized = 'hawk.'.self::HEADER_VERSION.'.'.$type."\n".
- $attributes->timestamp()."\n".
- $attributes->nonce()."\n".
- strtoupper($attributes->method())."\n".
- $attributes->resource()."\n".
- strtolower($attributes->host())."\n".
- $attributes->port()."\n".
- $attributes->hash()."\n";
-
- if ($attributes->ext()) {
- // TODO: escape ext
- $normalized .= $attributes->ext();
- }
-
- $normalized .= "\n";
-
- if ($attributes->app()) {
- $normalized .= $attributes->app()."\n".
- $attributes->dlg()."\n";
- }
-
- return $normalized;
- }
-}
diff --git a/src/Dflydev/Hawk/Header/FieldValueParserException.php b/src/Dflydev/Hawk/Header/FieldValueParserException.php
deleted file mode 100644
index 92cff34..0000000
--- a/src/Dflydev/Hawk/Header/FieldValueParserException.php
+++ /dev/null
@@ -1,7 +0,0 @@
-fieldName = $fieldName;
- $this->fieldValue = $fieldValue;
- $this->attributes = $attributes ?: array();
- }
-
- public function fieldName()
- {
- return $this->fieldName;
- }
-
- public function fieldValue()
- {
- return $this->fieldValue;
- }
-
- public function attributes(array $keys = null)
- {
- if (null === $keys) {
- return $this->attributes;
- }
-
- $attributes = array();
- foreach ($keys as $key) {
- if (isset($this->attributes[$key])) {
- $attributes[$key] = $this->attributes[$key];
- }
- }
-
- return $attributes;
- }
-
- public function attribute($key)
- {
- if (isset($this->attributes[$key])) {
- return $this->attributes[$key];
- }
- }
-}
diff --git a/src/Dflydev/Hawk/Header/HeaderFactory.php b/src/Dflydev/Hawk/Header/HeaderFactory.php
deleted file mode 100644
index 1e511b0..0000000
--- a/src/Dflydev/Hawk/Header/HeaderFactory.php
+++ /dev/null
@@ -1,43 +0,0 @@
- $value) {
- if ($index++ > 0) {
- $fieldValue .= ',';
- }
-
- $fieldValue .= ' '.$key.'="'.$value.'"';
- }
- }
-
- return new Header($fieldName, $fieldValue, $attributes);
- }
-
- public static function createFromString($fieldName, $fieldValue, array $requiredKeys = null)
- {
- return static::create(
- $fieldName,
- HeaderParser::parseFieldValue($fieldValue, $requiredKeys)
- );
- }
-
- public static function createFromHeaderObjectOrString($fieldName, $headerObjectOrString, $onError)
- {
- if (is_string($headerObjectOrString)) {
- return static::createFromString($fieldName, $headerObjectOrString);
- } elseif ($headerObjectOrString instanceof Header) {
- return $headerObjectOrString;
- } else {
- call_user_func($onError);
- }
- }
-}
diff --git a/src/Dflydev/Hawk/Nonce/CallbackNonceValidator.php b/src/Dflydev/Hawk/Nonce/CallbackNonceValidator.php
deleted file mode 100644
index 62bb53f..0000000
--- a/src/Dflydev/Hawk/Nonce/CallbackNonceValidator.php
+++ /dev/null
@@ -1,18 +0,0 @@
-callback = $callback;
- }
-
- public function validateNonce($nonce, $timestamp)
- {
- return call_user_func_array($this->callback, array($nonce, $timestamp));
- }
-}
diff --git a/src/Dflydev/Hawk/Server/Response.php b/src/Dflydev/Hawk/Server/Response.php
deleted file mode 100644
index 6f15828..0000000
--- a/src/Dflydev/Hawk/Server/Response.php
+++ /dev/null
@@ -1,28 +0,0 @@
-credentials = $credentials;
- $this->artifacts = $artifacts;
- }
-
- public function credentials()
- {
- return $this->credentials;
- }
-
- public function artifacts()
- {
- return $this->artifacts;
- }
-}
diff --git a/src/Dflydev/Hawk/Server/ServerInterface.php b/src/Dflydev/Hawk/Server/ServerInterface.php
deleted file mode 100644
index c1f4986..0000000
--- a/src/Dflydev/Hawk/Server/ServerInterface.php
+++ /dev/null
@@ -1,26 +0,0 @@
- $attributes
+ */
+ public function __construct(
+ private string $fieldName,
+ private string $fieldValue,
+ private array $attributes = []
+ ) {
+ }
+
+ public function fieldName(): string
+ {
+ return $this->fieldName;
+ }
+
+ public function fieldValue(): string
+ {
+ return $this->fieldValue;
+ }
+
+ /**
+ * @param string[]|null $keys
+ * @return array
+ */
+ public function attributes(array $keys = null): array
+ {
+ if (null === $keys) {
+ return $this->attributes;
+ }
+
+ $attributes = [];
+ foreach ($keys as $key) {
+ if (isset($this->attributes[$key])) {
+ $attributes[$key] = $this->attributes[$key];
+ }
+ }
+
+ return $attributes;
+ }
+
+ public function attribute(string $key): mixed
+ {
+ return $this->attributes[$key] ?? null;
+ }
+}
diff --git a/src/Header/HeaderFactory.php b/src/Header/HeaderFactory.php
new file mode 100644
index 0000000..439f2e4
--- /dev/null
+++ b/src/Header/HeaderFactory.php
@@ -0,0 +1,59 @@
+|null $attributes
+ */
+ public static function create(string $fieldName, array $attributes = null): Header
+ {
+ $fieldValue = 'Hawk';
+
+ if (null !== $attributes) {
+ $index = 0;
+ foreach ($attributes as $key => $value) {
+ if ($index++ > 0) {
+ $fieldValue .= ',';
+ }
+
+ $fieldValue .= ' ' . $key . '="' . $value . '"';
+ }
+ }
+
+ return new Header($fieldName, $fieldValue, $attributes ?? []);
+ }
+
+ /**
+ * @param string[]|null $requiredKeys
+ * @throws FieldValueParserException
+ * @throws NotHawkAuthorizationException
+ */
+ public static function createFromString(string $fieldName, string $fieldValue, array $requiredKeys = null): Header
+ {
+ return static::create(
+ $fieldName,
+ HeaderParser::parseFieldValue($fieldValue, $requiredKeys)
+ );
+ }
+
+ /**
+ * @param callable(): never $onError
+ * @throws FieldValueParserException
+ * @throws NotHawkAuthorizationException
+ */
+ public static function createFromHeaderObjectOrString(
+ string $fieldName,
+ mixed $headerObjectOrString,
+ callable $onError
+ ): Header {
+ if (is_string($headerObjectOrString)) {
+ return static::createFromString($fieldName, $headerObjectOrString);
+ }
+ if ($headerObjectOrString instanceof Header) {
+ return $headerObjectOrString;
+ }
+ call_user_func($onError);
+ }
+}
diff --git a/src/Dflydev/Hawk/Header/HeaderParser.php b/src/Header/HeaderParser.php
similarity index 56%
rename from src/Dflydev/Hawk/Header/HeaderParser.php
rename to src/Header/HeaderParser.php
index a423a50..36a051b 100644
--- a/src/Dflydev/Hawk/Header/HeaderParser.php
+++ b/src/Header/HeaderParser.php
@@ -4,32 +4,40 @@
class HeaderParser
{
- public static function parseFieldValue($fieldValue, array $requiredKeys = null)
+ /**
+ * @param string[]|null $requiredKeys
+ * @return array
+ * @throws FieldValueParserException
+ */
+ public static function parseFieldValue(string $fieldValue, array $requiredKeys = null): array
{
- if (0 !== strpos($fieldValue, 'Hawk')) {
- throw new NotHawkAuthorizationException;
+ if (!str_starts_with($fieldValue, 'Hawk')) {
+ throw new NotHawkAuthorizationException();
}
- $attributes = array();
+ $attributes = [];
$fieldValue = substr($fieldValue, 5);
foreach (explode(', ', $fieldValue) as $part) {
$equalsPos = strpos($part, '=');
+ if ($equalsPos === false) {
+ throw new FieldValueParserException('field did not contain a "="');
+ }
$key = substr($part, 0, $equalsPos);
$value = substr($part, $equalsPos + 1);
$attributes[$key] = trim($value, '"');
}
if (null !== $requiredKeys) {
- $missingKeys = array();
+ $missingKeys = [];
foreach ($requiredKeys as $requiredKey) {
if (!isset($attributes[$requiredKey])) {
$missingKeys[] = $requiredKey;
}
}
- if (count($missingKeys)) {
+ if ($missingKeys !== []) {
throw new FieldValueParserException(
- "Field value was missing the following required key(s): ".implode(', ', $missingKeys)
+ "Field value was missing the following required key(s): " . implode(', ', $missingKeys)
);
}
}
diff --git a/src/Dflydev/Hawk/Header/NotHawkAuthorizationException.php b/src/Header/NotHawkAuthorizationException.php
similarity index 69%
rename from src/Dflydev/Hawk/Header/NotHawkAuthorizationException.php
rename to src/Header/NotHawkAuthorizationException.php
index 71d33fc..f3c3226 100644
--- a/src/Dflydev/Hawk/Header/NotHawkAuthorizationException.php
+++ b/src/Header/NotHawkAuthorizationException.php
@@ -2,7 +2,9 @@
namespace Dflydev\Hawk\Header;
-class NotHawkAuthorizationException extends \Exception
+use Exception;
+
+class NotHawkAuthorizationException extends Exception
{
public function __construct()
{
diff --git a/src/Nonce/CallbackNonceValidator.php b/src/Nonce/CallbackNonceValidator.php
new file mode 100644
index 0000000..9d4fcf3
--- /dev/null
+++ b/src/Nonce/CallbackNonceValidator.php
@@ -0,0 +1,18 @@
+callback, [$nonce, $timestamp]);
+ }
+}
diff --git a/src/Dflydev/Hawk/Nonce/DefaultNonceProviderFactory.php b/src/Nonce/DefaultNonceProviderFactory.php
similarity index 68%
rename from src/Dflydev/Hawk/Nonce/DefaultNonceProviderFactory.php
rename to src/Nonce/DefaultNonceProviderFactory.php
index f0361db..bddd9c9 100644
--- a/src/Dflydev/Hawk/Nonce/DefaultNonceProviderFactory.php
+++ b/src/Nonce/DefaultNonceProviderFactory.php
@@ -6,9 +6,9 @@
class DefaultNonceProviderFactory
{
- public static function create()
+ public static function create(): NonceProvider
{
- $factory = new Factory;
+ $factory = new Factory();
return new NonceProvider($factory->getLowStrengthGenerator());
}
diff --git a/src/Dflydev/Hawk/Nonce/NonceProvider.php b/src/Nonce/NonceProvider.php
similarity index 66%
rename from src/Dflydev/Hawk/Nonce/NonceProvider.php
rename to src/Nonce/NonceProvider.php
index 3d60a6a..96a172a 100644
--- a/src/Dflydev/Hawk/Nonce/NonceProvider.php
+++ b/src/Nonce/NonceProvider.php
@@ -6,14 +6,11 @@
class NonceProvider implements NonceProviderInterface
{
- private $generator;
-
- public function __construct(Generator $generator)
+ public function __construct(private readonly Generator $generator)
{
- $this->generator = $generator;
}
- public function createNonce()
+ public function createNonce(): string
{
return $this->generator->generateString(
32,
diff --git a/src/Dflydev/Hawk/Nonce/NonceProviderInterface.php b/src/Nonce/NonceProviderInterface.php
similarity index 63%
rename from src/Dflydev/Hawk/Nonce/NonceProviderInterface.php
rename to src/Nonce/NonceProviderInterface.php
index 8a5d789..be51592 100644
--- a/src/Dflydev/Hawk/Nonce/NonceProviderInterface.php
+++ b/src/Nonce/NonceProviderInterface.php
@@ -4,5 +4,5 @@
interface NonceProviderInterface
{
- public function createNonce();
+ public function createNonce(): string;
}
diff --git a/src/Dflydev/Hawk/Nonce/NonceValidatorInterface.php b/src/Nonce/NonceValidatorInterface.php
similarity index 51%
rename from src/Dflydev/Hawk/Nonce/NonceValidatorInterface.php
rename to src/Nonce/NonceValidatorInterface.php
index 2a8f9c6..7c5beb2 100644
--- a/src/Dflydev/Hawk/Nonce/NonceValidatorInterface.php
+++ b/src/Nonce/NonceValidatorInterface.php
@@ -4,5 +4,5 @@
interface NonceValidatorInterface
{
- public function validateNonce($nonce, $timestamp);
+ public function validateNonce(string $nonce, int $timestamp): bool;
}
diff --git a/src/Server/Response.php b/src/Server/Response.php
new file mode 100644
index 0000000..73a9510
--- /dev/null
+++ b/src/Server/Response.php
@@ -0,0 +1,25 @@
+credentials;
+ }
+
+ public function artifacts(): Artifacts
+ {
+ return $this->artifacts;
+ }
+}
diff --git a/src/Dflydev/Hawk/Server/Server.php b/src/Server/Server.php
similarity index 68%
rename from src/Dflydev/Hawk/Server/Server.php
rename to src/Server/Server.php
index 1a2bab1..aa2725b 100644
--- a/src/Dflydev/Hawk/Server/Server.php
+++ b/src/Server/Server.php
@@ -2,71 +2,40 @@
namespace Dflydev\Hawk\Server;
-use Dflydev\Hawk\Credentials\CallbackCredentialsProvider;
use Dflydev\Hawk\Credentials\CredentialsInterface;
use Dflydev\Hawk\Credentials\CredentialsProviderInterface;
use Dflydev\Hawk\Crypto\Artifacts;
use Dflydev\Hawk\Crypto\Crypto;
use Dflydev\Hawk\Header\Header;
use Dflydev\Hawk\Header\HeaderFactory;
-use Dflydev\Hawk\Nonce\CallbackNonceValidator;
use Dflydev\Hawk\Nonce\NonceValidatorInterface;
use Dflydev\Hawk\Time\TimeProviderInterface;
+use InvalidArgumentException;
+/**
+ * @see \Dflydev\Hawk\Server\ServerTest
+ */
class Server implements ServerInterface
{
- private $crypto;
- private $credentialsProvider;
- private $timeProvider;
- private $nonceValidator;
- private $timestampSkewSec;
- private $localtimeOffsetSec;
-
public function __construct(
- Crypto $crypto,
- $credentialsProvider,
- TimeProviderInterface $timeProvider,
- $nonceValidator,
- $timestampSkewSec,
- $localtimeOffsetSec
+ private readonly Crypto $crypto,
+ private readonly CredentialsProviderInterface $credentialsProvider,
+ private readonly TimeProviderInterface $timeProvider,
+ private readonly NonceValidatorInterface $nonceValidator,
+ private int $timestampSkewSec,
+ private int $localtimeOffsetSec
) {
- if (!$credentialsProvider instanceof CredentialsProviderInterface) {
- if (is_callable($credentialsProvider)) {
- $credentialsProvider = new CallbackCredentialsProvider($credentialsProvider);
- } else {
- throw new \InvalidArgumentException(
- "Credentials provider must implement CredentialsProviderInterface or must be callable"
- );
- }
- }
-
- if (!$nonceValidator instanceof NonceValidatorInterface) {
- if (is_callable($nonceValidator)) {
- $nonceValidator = new CallbackNonceValidator($nonceValidator);
- } else {
- throw new \InvalidArgumentException(
- "Nonce validator must implement NonceValidatorInterface or must be callable"
- );
- }
- }
-
- $this->crypto = $crypto;
- $this->credentialsProvider = $credentialsProvider;
- $this->timeProvider = $timeProvider;
- $this->nonceValidator = $nonceValidator;
- $this->timestampSkewSec = $timestampSkewSec;
- $this->localtimeOffsetSec = $localtimeOffsetSec;
}
public function authenticate(
- $method,
- $host,
- $port,
- $resource,
- $contentType = null,
- $payload = null,
- $headerObjectOrString = null
- ) {
+ string $method,
+ string $host,
+ mixed $port,
+ mixed $resource,
+ string $contentType = null,
+ mixed $payload = null,
+ mixed $headerObjectOrString = null
+ ): Response {
if (null === $headerObjectOrString) {
throw new UnauthorizedException("Missing Authorization header");
}
@@ -74,7 +43,7 @@ public function authenticate(
$header = HeaderFactory::createFromHeaderObjectOrString(
'Authorization',
$headerObjectOrString,
- function () {
+ function (): never {
throw new UnauthorizedException("Invalid Authorization header");
}
);
@@ -97,7 +66,7 @@ function () {
$header->attribute('dlg')
);
- foreach (array('id', 'ts', 'nonce', 'mac') as $requiredAttribute) {
+ foreach (['id', 'ts', 'nonce', 'mac'] as $requiredAttribute) {
if (null === $header->attribute($requiredAttribute)) {
throw new UnauthorizedException('Missing attributes');
}
@@ -137,13 +106,13 @@ function () {
$ts = $this->timeProvider->createTimestamp() + $this->localtimeOffsetSec;
$tsm = $this->crypto->calculateTsMac($ts, $credentials);
- throw new UnauthorizedException('Stale timestamp', array('ts' => $ts, 'tsm' => $tsm));
+ throw new UnauthorizedException('Stale timestamp', ['ts' => $ts, 'tsm' => $tsm]);
}
return new Response($credentials, $artifacts);
}
- public function createHeader(CredentialsInterface $credentials, Artifacts $artifacts, array $options = array())
+ public function createHeader(CredentialsInterface $credentials, Artifacts $artifacts, array $options = []): Header
{
if (isset($options['payload']) || isset($options['content_type'])) {
if (isset($options['payload']) && isset($options['content_type'])) {
@@ -151,7 +120,7 @@ public function createHeader(CredentialsInterface $credentials, Artifacts $artif
$contentType = $options['content_type'];
$hash = $this->crypto->calculatePayloadHash($payload, $credentials->algorithm(), $contentType);
} else {
- throw new \InvalidArgumentException(
+ throw new InvalidArgumentException(
"If one of 'payload' and 'content_type' are specified, both must be specified."
);
}
@@ -161,7 +130,7 @@ public function createHeader(CredentialsInterface $credentials, Artifacts $artif
$hash = null;
}
- $ext = isset($options['ext']) ? $options['ext'] : null;
+ $ext = $options['ext'] ?? null;
$responseArtifacts = new Artifacts(
$artifacts->method(),
@@ -178,9 +147,7 @@ public function createHeader(CredentialsInterface $credentials, Artifacts $artif
$artifacts->dlg()
);
- $attributes = array(
- 'mac' => $this->crypto->calculateMac('response', $credentials, $responseArtifacts),
- );
+ $attributes = ['mac' => $this->crypto->calculateMac('response', $credentials, $responseArtifacts)];
if ($hash !== null) {
$attributes['hash'] = $hash;
@@ -195,47 +162,49 @@ public function createHeader(CredentialsInterface $credentials, Artifacts $artif
public function authenticatePayload(
CredentialsInterface $credentials,
- $payload,
- $contentType,
- $hash
- ) {
+ mixed $payload,
+ string $contentType,
+ string $hash
+ ): bool {
$calculatedHash = $this->crypto->calculatePayloadHash($payload, $credentials->algorithm(), $contentType);
return $this->crypto->fixedTimeComparison($calculatedHash, $hash);
}
public function authenticateBewit(
- $host,
- $port,
- $resource
- ) {
+ string $host,
+ int $port,
+ mixed $resource
+ ): Response {
// Measure now before any other processing
$now = $this->timeProvider->createTimestamp() + $this->localtimeOffsetSec;
- if (!preg_match(
- '/^(\/.*)([\?&])bewit\=([^&$]*)(?:&(.+))?$/',
- $resource,
- $resourceParts
- )) {
+ if (
+ !preg_match(
+ '/^(\/.*)([?&])bewit=([^&$]*)(?:&(.+))?$/',
+ (string) $resource,
+ $resourceParts
+ )
+ ) {
// TODO: Should this do something else?
throw new UnauthorizedException('Malformed resource or does not contan bewit');
}
$bewit = base64_decode(str_replace(
- array('-', '_', '', ''),
- array('+', '/', '=', "\n"),
+ ['-', '_', '', ''],
+ ['+', '/', '=', "\n"],
$resourceParts[3]
));
- list ($id, $exp, $mac, $ext) = explode('\\', $bewit);
+ [$id, $exp, $mac, $ext] = explode('\\', $bewit);
- if ($exp < $now) {
+ if ((int)$exp < $now) {
throw new UnauthorizedException('Access expired');
}
$resource = $resourceParts[1];
if (isset($resourceParts[4])) {
- $resource .= $resourceParts[2].$resourceParts[4];
+ $resource .= $resourceParts[2] . $resourceParts[4];
}
$artifacts = new Artifacts(
@@ -243,7 +212,7 @@ public function authenticateBewit(
$host,
$port,
$resource,
- $exp,
+ (int)$exp,
'',
$ext
);
diff --git a/src/Dflydev/Hawk/Server/ServerBuilder.php b/src/Server/ServerBuilder.php
similarity index 50%
rename from src/Dflydev/Hawk/Server/ServerBuilder.php
rename to src/Server/ServerBuilder.php
index 9c94c41..efd2d4b 100644
--- a/src/Dflydev/Hawk/Server/ServerBuilder.php
+++ b/src/Server/ServerBuilder.php
@@ -2,66 +2,67 @@
namespace Dflydev\Hawk\Server;
+use Dflydev\Hawk\Credentials\CredentialsProviderInterface;
use Dflydev\Hawk\Crypto\Crypto;
+use Dflydev\Hawk\Nonce\CallbackNonceValidator;
+use Dflydev\Hawk\Nonce\NonceValidatorInterface;
use Dflydev\Hawk\Time\DefaultTimeProviderFactory;
use Dflydev\Hawk\Time\TimeProviderInterface;
class ServerBuilder
{
- private $crypto;
- private $credentialsProvider;
- private $timeProvider;
- private $nonceValidator;
- private $timestampSkewSec;
- private $localtimeOffsetSec;
-
- public function __construct($credentialsProvider)
+ private ?Crypto $crypto = null;
+ private ?TimeProviderInterface $timeProvider = null;
+ private ?NonceValidatorInterface $nonceValidator = null;
+ private ?int $timestampSkewSec = null;
+ private ?int $localtimeOffsetSec = null;
+
+ public function __construct(private CredentialsProviderInterface $credentialsProvider)
{
- $this->credentialsProvider = $credentialsProvider;
}
- public function setCrypto(Crypto $crypto)
+ public function setCrypto(Crypto $crypto): static
{
$this->crypto = $crypto;
return $this;
}
- public function setTimeProvider(TimeProviderInterface $timeProvider)
+ public function setTimeProvider(TimeProviderInterface $timeProvider): static
{
$this->timeProvider = $timeProvider;
return $this;
}
- public function setNonceValidator($nonceValidator)
+ public function setNonceValidator(NonceValidatorInterface $nonceValidator): static
{
$this->nonceValidator = $nonceValidator;
return $this;
}
- public function setTimestampSkewSec($timestampSkewSec = null)
+ public function setTimestampSkewSec(?int $timestampSkewSec = null): static
{
$this->timestampSkewSec = $timestampSkewSec;
return $this;
}
- public function setLocaltimeOffsetSec($localtimeOffsetSec = null)
+ public function setLocaltimeOffsetSec(?int $localtimeOffsetSec = null): static
{
$this->localtimeOffsetSec = $localtimeOffsetSec;
return $this;
}
- public function build()
+ public function build(): Server
{
- $crypto = $this->crypto ?: new Crypto;
+ $crypto = $this->crypto ?: new Crypto();
$timeProvider = $this->timeProvider ?: DefaultTimeProviderFactory::create();
- $nonceValidator = $this->nonceValidator ?: function($nonce, $timestamp) {
- return true;
- };
+ $nonceValidator = $this->nonceValidator ?: new CallbackNonceValidator(
+ static fn(string $nonce, int $timestamp): bool => true
+ );
$timestampSkewSec = $this->timestampSkewSec ?: 60;
$localtimeOffsetSec = $this->localtimeOffsetSec ?: 0;
@@ -75,7 +76,7 @@ public function build()
);
}
- public static function create($credentialsProvider)
+ public static function create(CredentialsProviderInterface $credentialsProvider): static
{
return new static($credentialsProvider);
}
diff --git a/src/Server/ServerInterface.php b/src/Server/ServerInterface.php
new file mode 100644
index 0000000..e3c35a2
--- /dev/null
+++ b/src/Server/ServerInterface.php
@@ -0,0 +1,32 @@
+ $options
+ */
+ public function createHeader(CredentialsInterface $credentials, Artifacts $artifacts, array $options = []): Header;
+
+ public function authenticatePayload(
+ CredentialsInterface $credentials,
+ mixed $payload,
+ string $contentType,
+ string $hash
+ ): bool;
+}
diff --git a/src/Dflydev/Hawk/Server/UnauthorizedException.php b/src/Server/UnauthorizedException.php
similarity index 52%
rename from src/Dflydev/Hawk/Server/UnauthorizedException.php
rename to src/Server/UnauthorizedException.php
index 0324ff0..d1074c6 100644
--- a/src/Dflydev/Hawk/Server/UnauthorizedException.php
+++ b/src/Server/UnauthorizedException.php
@@ -2,27 +2,30 @@
namespace Dflydev\Hawk\Server;
+use Exception;
+use Dflydev\Hawk\Header\Header;
use Dflydev\Hawk\Header\HeaderFactory;
-class UnauthorizedException extends \Exception
+class UnauthorizedException extends Exception
{
- private $attributes;
- private $header;
+ private ?Header $header = null;
- public function __construct($message = null, array $attributes = null)
+ /**
+ * @param array $attributes
+ */
+ public function __construct(string $message = '', private array $attributes = [])
{
parent::__construct($message);
- $this->attributes = $attributes ?: array();
}
- public function getHeader()
+ public function getHeader(): Header
{
if (null !== $this->header) {
return $this->header;
}
$attributes = $this->attributes;
- if ($this->getMessage()) {
+ if ($this->getMessage() !== '' && $this->getMessage() !== '0') {
$attributes['error'] = $this->getMessage();
}
diff --git a/src/Dflydev/Hawk/Time/ConstantTimeProvider.php b/src/Time/ConstantTimeProvider.php
similarity index 55%
rename from src/Dflydev/Hawk/Time/ConstantTimeProvider.php
rename to src/Time/ConstantTimeProvider.php
index 45d1a23..f2ebd29 100644
--- a/src/Dflydev/Hawk/Time/ConstantTimeProvider.php
+++ b/src/Time/ConstantTimeProvider.php
@@ -4,14 +4,11 @@
class ConstantTimeProvider implements TimeProviderInterface
{
- private $time;
-
- public function __construct($time)
+ public function __construct(private int $time)
{
- $this->time = $time;
}
- public function createTimestamp()
+ public function createTimestamp(): int
{
return $this->time;
}
diff --git a/src/Dflydev/Hawk/Time/DefaultTimeProviderFactory.php b/src/Time/DefaultTimeProviderFactory.php
similarity index 50%
rename from src/Dflydev/Hawk/Time/DefaultTimeProviderFactory.php
rename to src/Time/DefaultTimeProviderFactory.php
index c475bea..df8cc7f 100644
--- a/src/Dflydev/Hawk/Time/DefaultTimeProviderFactory.php
+++ b/src/Time/DefaultTimeProviderFactory.php
@@ -4,8 +4,8 @@
class DefaultTimeProviderFactory
{
- public static function create()
+ public static function create(): TimeProvider
{
- return new TimeProvider;
+ return new TimeProvider();
}
}
diff --git a/src/Dflydev/Hawk/Time/TimeProvider.php b/src/Time/TimeProvider.php
similarity index 74%
rename from src/Dflydev/Hawk/Time/TimeProvider.php
rename to src/Time/TimeProvider.php
index a57ce1a..029a449 100644
--- a/src/Dflydev/Hawk/Time/TimeProvider.php
+++ b/src/Time/TimeProvider.php
@@ -4,7 +4,7 @@
class TimeProvider implements TimeProviderInterface
{
- public function createTimestamp()
+ public function createTimestamp(): int
{
return time();
}
diff --git a/src/Dflydev/Hawk/Time/TimeProviderInterface.php b/src/Time/TimeProviderInterface.php
similarity index 62%
rename from src/Dflydev/Hawk/Time/TimeProviderInterface.php
rename to src/Time/TimeProviderInterface.php
index 9d48f97..4abc42a 100644
--- a/src/Dflydev/Hawk/Time/TimeProviderInterface.php
+++ b/src/Time/TimeProviderInterface.php
@@ -4,5 +4,5 @@
interface TimeProviderInterface
{
- public function createTimestamp();
+ public function createTimestamp(): int;
}
diff --git a/tests/unit/Dflydev/Hawk/Client/ClientTest.php b/tests/Unit/Client/ClientTest.php
similarity index 55%
rename from tests/unit/Dflydev/Hawk/Client/ClientTest.php
rename to tests/Unit/Client/ClientTest.php
index 7bd9cf5..167ac62 100644
--- a/tests/unit/Dflydev/Hawk/Client/ClientTest.php
+++ b/tests/Unit/Client/ClientTest.php
@@ -1,17 +1,16 @@
build();
@@ -21,15 +20,14 @@ public function shouldCreateBewit()
'exqbZWtykFZIh2D7cXi9dA'
);
- $this->assertEquals(
- 'ZXhxYlpXdHlrRlpJaDJEN2NYaTlkQVwxMzY4OTk2ODAwXE8wbWhwcmdvWHFGNDhEbHc1RldBV3ZWUUlwZ0dZc3FzWDc2dHBvNkt5cUk9XA',
+ $this->assertSame(
+ 'ZXhxYlpXdHlrRlpJaDJEN2NYaTlkQVwxMzY4OTk2ODAwXE8wbWhwcmdv' .
+ 'WHFGNDhEbHc1RldBV3ZWUUlwZ0dZc3FzWDc2dHBvNkt5cUk9XA',
$client->createBewit(
$tentTestVectorsCredentials,
'https://example.com/posts',
0,
- array(
- 'timestamp' => 1368996800,
- )
+ ['timestamp' => 1368996800]
)
);
}
diff --git a/tests/Unit/Crypto/ArtifactsTest.php b/tests/Unit/Crypto/ArtifactsTest.php
new file mode 100644
index 0000000..ba96110
--- /dev/null
+++ b/tests/Unit/Crypto/ArtifactsTest.php
@@ -0,0 +1,42 @@
+assertSame('testmethod', $artifacts->method());
+ $this->assertSame('testhost', $artifacts->host());
+ $this->assertSame(80, $artifacts->port());
+ $this->assertSame('testresource', $artifacts->resource());
+ $this->assertSame($time, $artifacts->timestamp());
+ $this->assertSame('testnonce', $artifacts->nonce());
+ $this->assertSame('testext', $artifacts->ext());
+ $this->assertSame('testpayload', $artifacts->payload());
+ $this->assertSame('testcontenttype', $artifacts->contentType());
+ $this->assertSame('testhash', $artifacts->hash());
+ $this->assertSame('testapp', $artifacts->app());
+ $this->assertSame('testdlg', $artifacts->dlg());
+ }
+}
diff --git a/tests/Unit/Crypto/CryptoTest.php b/tests/Unit/Crypto/CryptoTest.php
new file mode 100644
index 0000000..bf82ee8
--- /dev/null
+++ b/tests/Unit/Crypto/CryptoTest.php
@@ -0,0 +1,215 @@
+calculatePayloadHash(
+ $payload,
+ $algorithm,
+ $contentType
+ );
+
+ $this->assertSame($expectedHash, $calculatedHash);
+ }
+
+ public static function payloadDataProvider(): Generator
+ {
+ yield [
+ 'neQFHgYKl/jFqDINrC21uLS0gkFglTz789rzcSr7HYU=',
+ '{"type":"https://tent.io/types/status/v0#"}',
+ 'sha256',
+ 'application/vnd.tent.post.v0+json'
+ ];
+ }
+
+ #[Test]
+ #[DataProvider('macDataProvider')]
+ public function shouldCalculateMac(
+ string $expectedMac,
+ string $type,
+ CredentialsInterface $credentials,
+ Artifacts $artifacts
+ ): void {
+ $crypto = new Crypto();
+
+ $calculatedMac = $crypto->calculateMac($type, $credentials, $artifacts);
+
+ $this->assertSame($expectedMac, $calculatedMac);
+ }
+
+ public static function macDataProvider(): Generator
+ {
+ $tentTestVectorsCredentials = new Credentials(
+ 'HX9QcbD-r3ItFEnRcAuOSg',
+ 'sha256',
+ 'exqbZWtykFZIh2D7cXi9dA'
+ );
+
+ $tentTestVectorsAttributes = [
+ 'method' => 'POST',
+ 'host' => 'example.com',
+ 'port' => 443,
+ 'resource' => '/posts',
+ 'timestamp' => 1368996800,
+ 'nonce' => '3yuYCD4Z',
+ 'payload' => '{"type":"https://tent.io/types/status/v0#"}',
+ 'content_type' => 'application/vnd.tent.post.v0+json',
+ 'hash' => 'neQFHgYKl/jFqDINrC21uLS0gkFglTz789rzcSr7HYU='
+ ];
+ yield [
+ //
+ // App request w/hash
+ //
+ '2sttHCQJG9ejj1x7eCi35FP23Miu9VtlaUgwk68DTpM=',
+ 'header',
+ $tentTestVectorsCredentials,
+ new Artifacts(
+ $tentTestVectorsAttributes['method'],
+ $tentTestVectorsAttributes['host'],
+ $tentTestVectorsAttributes['port'],
+ $tentTestVectorsAttributes['resource'],
+ $tentTestVectorsAttributes['timestamp'],
+ $tentTestVectorsAttributes['nonce'],
+ null,
+ $tentTestVectorsAttributes['payload'],
+ $tentTestVectorsAttributes['content_type'],
+ $tentTestVectorsAttributes['hash'],
+ 'wn6yzHGe5TLaT-fvOPbAyQ'
+ ),
+ ];
+ yield [
+ //
+ // Server Response (App request w/hash)
+ //
+ 'lTG3kTBr33Y97Q4KQSSamu9WY/mOUKnZzq/ho9x+yxw=',
+ 'response',
+ $tentTestVectorsCredentials,
+ new Artifacts(
+ $tentTestVectorsAttributes['method'],
+ $tentTestVectorsAttributes['host'],
+ $tentTestVectorsAttributes['port'],
+ $tentTestVectorsAttributes['resource'],
+ $tentTestVectorsAttributes['timestamp'],
+ $tentTestVectorsAttributes['nonce'],
+ null,
+ null,
+ null,
+ null,
+ 'wn6yzHGe5TLaT-fvOPbAyQ'
+ ),
+ ];
+ yield [
+ //
+ // Relationship Request
+ //
+ 'OO2ldBDSw8KmNHlEdTC4BciIl8+uiuCRvCnJ9KkcR3Y=',
+ 'header',
+ $tentTestVectorsCredentials,
+ new Artifacts(
+ $tentTestVectorsAttributes['method'],
+ $tentTestVectorsAttributes['host'],
+ $tentTestVectorsAttributes['port'],
+ $tentTestVectorsAttributes['resource'],
+ $tentTestVectorsAttributes['timestamp'],
+ $tentTestVectorsAttributes['nonce']
+ ),
+ ];
+ yield [
+ //
+ // Server Response w/ hash (Relationship Request)
+ //
+ 'LvxASIZ2gop5cwE2mNervvz6WXkPmVslwm11MDgEZ5E=',
+ 'response',
+ $tentTestVectorsCredentials,
+ new Artifacts(
+ $tentTestVectorsAttributes['method'],
+ $tentTestVectorsAttributes['host'],
+ $tentTestVectorsAttributes['port'],
+ $tentTestVectorsAttributes['resource'],
+ $tentTestVectorsAttributes['timestamp'],
+ $tentTestVectorsAttributes['nonce'],
+ null,
+ $tentTestVectorsAttributes['payload'],
+ $tentTestVectorsAttributes['content_type'],
+ $tentTestVectorsAttributes['hash']
+ ),
+ ];
+ yield [
+ //
+ // Bewit (GET /posts)
+ //
+ 'O0mhprgoXqF48Dlw5FWAWvVQIpgGYsqsX76tpo6KyqI=',
+ 'bewit',
+ $tentTestVectorsCredentials,
+ new Artifacts(
+ 'GET',
+ $tentTestVectorsAttributes['host'],
+ $tentTestVectorsAttributes['port'],
+ $tentTestVectorsAttributes['resource'],
+ $tentTestVectorsAttributes['timestamp'],
+ ''
+ ),
+ ];
+ }
+
+ #[Test]
+ #[DataProvider('tsMacDataProvider')]
+ public function shouldCalculateTsMac(
+ string $expectedTsMac,
+ int $ts,
+ CredentialsInterface $credentials
+ ): void {
+ $crypto = new Crypto();
+
+ $calculatedTsMac = $crypto->calculateTsMac($ts, $credentials);
+
+ $this->assertSame($expectedTsMac, $calculatedTsMac);
+ }
+
+ public static function tsMacDataProvider(): Generator
+ {
+ $tentTestVectorsCredentials = new Credentials(
+ 'HX9QcbD-r3ItFEnRcAuOSg',
+ 'sha256',
+ 'exqbZWtykFZIh2D7cXi9dA'
+ );
+
+ $tentTestVectorsAttributes = [
+ 'method' => 'POST',
+ 'host' => 'example.com',
+ 'port' => 443,
+ 'resource' => '/posts',
+ 'timestamp' => 1368996800,
+ 'nonce' => '3yuYCD4Z',
+ 'payload' => '{"type":"https://tent.io/types/status/v0#"}',
+ 'content_type' => 'application/vnd.tent.post.v0+json',
+ 'hash' => 'neQFHgYKl/jFqDINrC21uLS0gkFglTz789rzcSr7HYU='
+ ];
+
+ yield [
+ 'HPDcD5S3Kw7LM/oyoXKcgv2Z30RnOLAI5ebXpYDGfo4=',
+ $tentTestVectorsAttributes['timestamp'],
+ $tentTestVectorsCredentials
+ ];
+ }
+}
diff --git a/tests/Unit/Server/ServerTest.php b/tests/Unit/Server/ServerTest.php
new file mode 100644
index 0000000..7f7503d
--- /dev/null
+++ b/tests/Unit/Server/ServerTest.php
@@ -0,0 +1,36 @@
+ new Credentials(
+ 'HX9QcbD-r3ItFEnRcAuOSg',
+ 'sha256',
+ 'exqbZWtykFZIh2D7cXi9dA'
+ );
+
+ $server = ServerBuilder::create(new CallbackCredentialsProvider($credentialsProvider))
+ ->setTimeProvider(new ConstantTimeProvider(1368996800))
+ ->build();
+
+ $response = $server->authenticateBewit(
+ 'example.com',
+ 443,
+ '/posts?bewit=ZXhxYlpXdHlrRlpJaDJEN2NYaTlkQVwxMzY4OTk2' .
+ 'ODAwXE8wbWhwcmdvWHFGNDhEbHc1RldBV3ZWUUlwZ0dZc3FzWDc2dHBvNkt5cUk9XA'
+ );
+
+ $this->assertSame('/posts', $response->artifacts()->resource());
+ }
+}
diff --git a/tests/unit/Dflydev/Hawk/Crypto/ArtifactsTest.php b/tests/unit/Dflydev/Hawk/Crypto/ArtifactsTest.php
deleted file mode 100644
index 4b608d7..0000000
--- a/tests/unit/Dflydev/Hawk/Crypto/ArtifactsTest.php
+++ /dev/null
@@ -1,38 +0,0 @@
-assertEquals('testmethod', $artifacts->method());
- $this->assertEquals('testhost', $artifacts->host());
- $this->assertEquals('testport', $artifacts->port());
- $this->assertEquals('testresource', $artifacts->resource());
- $this->assertEquals('testtimestamp', $artifacts->timestamp());
- $this->assertEquals('testnonce', $artifacts->nonce());
- $this->assertEquals('testext', $artifacts->ext());
- $this->assertEquals('testpayload', $artifacts->payload());
- $this->assertEquals('testcontenttype', $artifacts->contentType());
- $this->assertEquals('testhash', $artifacts->hash());
- $this->assertEquals('testapp', $artifacts->app());
- $this->assertEquals('testdlg', $artifacts->dlg());
- }
-}
diff --git a/tests/unit/Dflydev/Hawk/Crypto/CryptoTest.php b/tests/unit/Dflydev/Hawk/Crypto/CryptoTest.php
deleted file mode 100644
index e4f5ade..0000000
--- a/tests/unit/Dflydev/Hawk/Crypto/CryptoTest.php
+++ /dev/null
@@ -1,238 +0,0 @@
-calculatePayloadHash(
- $payload,
- $algorithm,
- $contentType
- );
-
- $this->assertEquals($expectedHash, $calculatedHash);
- }
-
- public function payloadDataProvider()
- {
- return array(
- array(
- 'neQFHgYKl/jFqDINrC21uLS0gkFglTz789rzcSr7HYU=',
- '{"type":"https://tent.io/types/status/v0#"}',
- 'sha256',
- 'application/vnd.tent.post.v0+json'
- )
- );
- }
-
- /**
- * @test
- * @dataProvider macDataProvider
- */
- public function shouldCalculateMac(
- $expectedMac,
- $type,
- CredentialsInterface $credentials,
- Artifacts $artifacts
- ) {
- $crypto = new Crypto;
-
- $calculatedMac = $crypto->calculateMac($type, $credentials, $artifacts);
-
- $this->assertEquals($expectedMac, $calculatedMac);
- }
-
- public function macDataProvider()
- {
- $tentTestVectorsCredentials = new Credentials(
- 'HX9QcbD-r3ItFEnRcAuOSg',
- 'sha256',
- 'exqbZWtykFZIh2D7cXi9dA'
- );
-
- $tentTestVectorsAttributes = array(
- 'method' => 'POST',
- 'host' => 'example.com',
- 'port' => 443,
- 'resource' => '/posts',
- 'timestamp' => 1368996800,
- 'nonce' => '3yuYCD4Z',
- 'payload' => '{"type":"https://tent.io/types/status/v0#"}',
- 'content_type' => 'application/vnd.tent.post.v0+json',
- 'hash' => 'neQFHgYKl/jFqDINrC21uLS0gkFglTz789rzcSr7HYU=',
- );
-
- return array(
- array(
-
- //
- // App request w/hash
- //
-
- '2sttHCQJG9ejj1x7eCi35FP23Miu9VtlaUgwk68DTpM=',
-
- 'header',
- $tentTestVectorsCredentials,
- new Artifacts(
- $tentTestVectorsAttributes['method'],
- $tentTestVectorsAttributes['host'],
- $tentTestVectorsAttributes['port'],
- $tentTestVectorsAttributes['resource'],
- $tentTestVectorsAttributes['timestamp'],
- $tentTestVectorsAttributes['nonce'],
- null,
- $tentTestVectorsAttributes['payload'],
- $tentTestVectorsAttributes['content_type'],
- $tentTestVectorsAttributes['hash'],
- 'wn6yzHGe5TLaT-fvOPbAyQ'
- ),
- ),
- array(
-
- //
- // Server Response (App request w/hash)
- //
-
- 'lTG3kTBr33Y97Q4KQSSamu9WY/mOUKnZzq/ho9x+yxw=',
-
- 'response',
- $tentTestVectorsCredentials,
- new Artifacts(
- $tentTestVectorsAttributes['method'],
- $tentTestVectorsAttributes['host'],
- $tentTestVectorsAttributes['port'],
- $tentTestVectorsAttributes['resource'],
- $tentTestVectorsAttributes['timestamp'],
- $tentTestVectorsAttributes['nonce'],
- null,
- null,
- null,
- null,
- 'wn6yzHGe5TLaT-fvOPbAyQ'
- ),
- ),
- array(
-
- //
- // Relationship Request
- //
-
- 'OO2ldBDSw8KmNHlEdTC4BciIl8+uiuCRvCnJ9KkcR3Y=',
-
- 'header',
- $tentTestVectorsCredentials,
- new Artifacts(
- $tentTestVectorsAttributes['method'],
- $tentTestVectorsAttributes['host'],
- $tentTestVectorsAttributes['port'],
- $tentTestVectorsAttributes['resource'],
- $tentTestVectorsAttributes['timestamp'],
- $tentTestVectorsAttributes['nonce']
- ),
- ),
- array(
-
- //
- // Server Response w/ hash (Relationship Request)
- //
-
- 'LvxASIZ2gop5cwE2mNervvz6WXkPmVslwm11MDgEZ5E=',
-
- 'response',
- $tentTestVectorsCredentials,
- new Artifacts(
- $tentTestVectorsAttributes['method'],
- $tentTestVectorsAttributes['host'],
- $tentTestVectorsAttributes['port'],
- $tentTestVectorsAttributes['resource'],
- $tentTestVectorsAttributes['timestamp'],
- $tentTestVectorsAttributes['nonce'],
- null,
- $tentTestVectorsAttributes['payload'],
- $tentTestVectorsAttributes['content_type'],
- $tentTestVectorsAttributes['hash']
- ),
- ),
- array(
-
- //
- // Bewit (GET /posts)
- //
-
- 'O0mhprgoXqF48Dlw5FWAWvVQIpgGYsqsX76tpo6KyqI=',
-
- 'bewit',
- $tentTestVectorsCredentials,
- new Artifacts(
- 'GET',
- $tentTestVectorsAttributes['host'],
- $tentTestVectorsAttributes['port'],
- $tentTestVectorsAttributes['resource'],
- $tentTestVectorsAttributes['timestamp'],
- ''
- ),
- ),
- );
- }
-
- /**
- * @test
- * @dataProvider tsMacDataProvider
- */
- public function shouldCalculateTsMac(
- $expectedTsMac,
- $ts,
- CredentialsInterface $credentials
- ) {
- $crypto = new Crypto;
-
- $calculatedTsMac = $crypto->calculateTsMac($ts, $credentials);
-
- $this->assertEquals($expectedTsMac, $calculatedTsMac);
- }
-
- public function tsMacDataProvider()
- {
- $tentTestVectorsCredentials = new Credentials(
- 'HX9QcbD-r3ItFEnRcAuOSg',
- 'sha256',
- 'exqbZWtykFZIh2D7cXi9dA'
- );
-
- $tentTestVectorsAttributes = array(
- 'method' => 'POST',
- 'host' => 'example.com',
- 'port' => 443,
- 'resource' => '/posts',
- 'timestamp' => 1368996800,
- 'nonce' => '3yuYCD4Z',
- 'payload' => '{"type":"https://tent.io/types/status/v0#"}',
- 'content_type' => 'application/vnd.tent.post.v0+json',
- 'hash' => 'neQFHgYKl/jFqDINrC21uLS0gkFglTz789rzcSr7HYU=',
- );
-
- return array(
- array(
- 'HPDcD5S3Kw7LM/oyoXKcgv2Z30RnOLAI5ebXpYDGfo4=',
-
- $tentTestVectorsAttributes['timestamp'],
- $tentTestVectorsCredentials,
- ),
- );
- }
-}
diff --git a/tests/unit/Dflydev/Hawk/Server/ServerTest.php b/tests/unit/Dflydev/Hawk/Server/ServerTest.php
deleted file mode 100644
index b9a6da0..0000000
--- a/tests/unit/Dflydev/Hawk/Server/ServerTest.php
+++ /dev/null
@@ -1,35 +0,0 @@
-setTimeProvider(new ConstantTimeProvider(1368996800))
- ->build();
-
- $response = $server->authenticateBewit(
- 'example.com',
- 443,
- '/posts?bewit=ZXhxYlpXdHlrRlpJaDJEN2NYaTlkQVwxMzY4OTk2ODAwXE8wbWhwcmdvWHFGNDhEbHc1RldBV3ZWUUlwZ0dZc3FzWDc2dHBvNkt5cUk9XA'
- );
-
- $this->assertEquals('/posts', $response->artifacts()->resource());
- }
-}