├── .gitignore ├── LICENSE ├── composer.json ├── src └── Dflydev │ └── Stack │ ├── WwwAuthenticateStackChallenge.php │ └── Authentication.php ├── README.md └── composer.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Dragonfly Development Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dflydev/stack-authentication", 3 | "description": "STACK-2 Authentication Middlewares", 4 | "keywords": ["stack", "stack-2"], 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Dragonfly Development Inc.", 9 | "email": "info@dflydev.com", 10 | "homepage": "http://dflydev.com" 11 | }, 12 | { 13 | "name": "Beau Simensen", 14 | "email": "beau@dflydev.com", 15 | "homepage": "http://beausimensen.com" 16 | } 17 | ], 18 | "autoload": { 19 | "psr-0": { 20 | "Dflydev\\Stack": "src" 21 | } 22 | }, 23 | "require": { 24 | "php": ">=5.4.0", 25 | "symfony/http-foundation": "~2.1", 26 | "symfony/http-kernel": "~2.1" 27 | }, 28 | "require-dev": { 29 | "phpunit/phpunit": "3.7.21", 30 | "silex/silex": "1.1.*@dev", 31 | "stack/builder": "~1.0@dev", 32 | "stack/callable-http-kernel": "~1.0@dev", 33 | "stack/inline": "~1.0@dev", 34 | "symfony/browser-kit": "~2.1" 35 | }, 36 | "extra": { 37 | "branch-alias": { 38 | "dev-master": "1.0-dev" 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Dflydev/Stack/WwwAuthenticateStackChallenge.php: -------------------------------------------------------------------------------- 1 | app = $app; 17 | $this->challenge = $challenge ?: function (Response $response) { 18 | return (new Response('Authentication not possible', 403)); 19 | }; 20 | } 21 | 22 | public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) 23 | { 24 | $response = $this->app->handle($request, $type, $catch); 25 | 26 | if ($response->getStatusCode()==401 && $response->headers->get('WWW-Authenticate') === 'Stack') { 27 | // By convention, we look for 401 response that has a WWW-Authenticate with field value of 28 | // Stack. In that case, we should pass the response to the delegatee's challenge callback. 29 | $response = call_user_func($this->challenge, $response); 30 | } 31 | 32 | return $response; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Dflydev/Stack/Authentication.php: -------------------------------------------------------------------------------- 1 | app = $app; 20 | 21 | if (!isset($options['challenge'])) { 22 | $options['challenge'] = function (Response $response) { 23 | // Default challenge is to not challenge. 24 | return $response; 25 | }; 26 | } 27 | 28 | if (!isset($options['check'])) { 29 | $options['check'] = function ( 30 | Request $request, 31 | $type = HttpKernelInterface::MASTER_REQUEST, 32 | $catch = true 33 | ) { 34 | // Default check is to see if the request has an authorization 35 | // header. 36 | return $request->headers->has('authorization'); 37 | }; 38 | } 39 | 40 | if (!isset($options['authenticate'])) { 41 | throw new \InvalidArgumentException("The 'authenticate' configuration is required"); 42 | } 43 | 44 | $this->challenge = $options['challenge']; 45 | $this->check = $options['check']; 46 | $this->authenticate = $options['authenticate']; 47 | $this->anonymous = $options['anonymous']; 48 | } 49 | 50 | public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) 51 | { 52 | if ($request->attributes->has('stack.authn.token')) { 53 | // If the request already has a Stack authentication token we 54 | // should wrap the application so that it has the option to 55 | // challenge if we get a 401 WWW-Authenticate: Stack response. 56 | // 57 | // Delegate immediately. 58 | return (new WwwAuthenticateStackChallenge($this->app, $this->challenge)) 59 | ->handle($request, $type, $catch); 60 | } 61 | 62 | if (call_user_func($this->check, $request, $type, $catch)) { 63 | // Check the request to see if we should authenticate. If we should, 64 | // we should call our authenticate callback and return its response. 65 | return call_user_func($this->authenticate, $this->app, $this->anonymous); 66 | } 67 | 68 | if ($this->anonymous) { 69 | // If anonymous requests are allowed we should wrap the application 70 | // so that it has the option to challenge if we get a 401 71 | // WWW-Authenticate: Stack response. 72 | // 73 | // Delegate immediately. 74 | return (new WwwAuthenticateStackChallenge($this->app, $this->challenge)) 75 | ->handle($request, $type, $catch); 76 | } 77 | 78 | // Since we do not allow anonymous requests we should challenge 79 | // immediately. 80 | return call_user_func($this->challenge, (new Response)->setStatusCode(401)); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | STACK-2 Authentication Middlewares 2 | ================================== 3 | 4 | A collection of [Stack][0] middlewares designed to help authentication 5 | middleware implementors adhere to the [STACK-2 Authentication][1] conventions. 6 | 7 | 8 | Installation 9 | ------------ 10 | 11 | Through [Composer][2] as [dflydev/stack-authentication][3]. 12 | 13 | 14 | Middlewares 15 | ----------- 16 | 17 | ### Authentication Middleware 18 | 19 | The Authentication middleware takes care of setting up the handling of an 20 | inbound request by taking care of some [STACK-2 Authentication][2] housekeeping 21 | tasks: 22 | 23 | * If the `stack.authn.token` is set, it wraps the application in 24 | `WwwAuthenticateStackChallenge` and delegates. 25 | * Checks the request by calling the **check** callback. The return value is a 26 | boolean. If true, the **authenticate** callback is called and its return 27 | value is returned. If false, we should not. The default check is to see if 28 | there is an Authorization header. 29 | * If anonymous requests are received and anonymous requests are allowed, it 30 | wraps the application in `WwwAuthenticateStackChallenge` and delegates. 31 | * Otherwise, it returns the result of the **challenge** callback. 32 | 33 | #### Usage 34 | 35 | ```php 36 | headers->has('authorization'); 51 | }; 52 | 53 | $challenge = function (Response $response) { 54 | // Assumptions that can be made: 55 | // * 401 status code 56 | // * WWW-Authenticate header with a value of "Stack" 57 | // 58 | // Expectations: 59 | // * MAY set WWW-Authenticate header to another value 60 | // * MAY return a brand new response (does not have to be 61 | // the original response) 62 | // * MUST return a response 63 | return $response; 64 | }; 65 | 66 | $authenticate = function (HttpKernelInterface $app, $anonymous) { 67 | // Assumptions that can be made: 68 | // * The $app can be delegated to at any time 69 | // * The anonymous boolean indicates whether or not we 70 | // SHOULD allow anonymous requests through or if we 71 | // should challenge immediately. 72 | // * Additional state, like $request, $type, and $catch 73 | // should be passed via use statement if they are needed. 74 | // 75 | // Expectations: 76 | // * SHOULD set 'stack.authn.token' attribute on the request 77 | // when authentication is successful. 78 | // * MAY delegate to the passed $app 79 | // * MAY return a custom response of any status (for example 80 | // returning a 302 or 400 status response is allowed) 81 | // * MUST return a response 82 | }; 83 | 84 | $app = new Authentication($app, [ 85 | 'challenge' => $challenge, 86 | 'check' => $check, 87 | 'authenticate' => $authenticate, 88 | 'anonymous' => true, // default: false 89 | ]); 90 | ``` 91 | 92 | ### WwwAuthenticateStackChallenge Middleware 93 | 94 | The WwwAuthenticateStackChallenge middleware takes care of setting up the 95 | handling of an outbound response by taking care of some 96 | [STACK-2 Authentication][2] housekeeping tasks: 97 | 98 | * If the response has a 401 status code and has a WWW-Authenticate header with 99 | the value of Stack, it returns the result of the **challenge** callback. 100 | * Otherwise the original response from the delegated app is returned. 101 | 102 | 103 | #### Usage 104 | 105 | ```php 106 | handle($request, $type, $catch); 125 | ``` 126 | 127 | 128 | License 129 | ------- 130 | 131 | MIT, see LICENSE. 132 | 133 | 134 | Community 135 | --------- 136 | 137 | If you have questions or want to help out, join us in the **#stackphp** or 138 | **#dflydev** channels on **irc.freenode.net**. 139 | 140 | 141 | [0]: http://stackphp.com/ 142 | [1]: http://stackphp.com/specs/STACK-2/ 143 | [2]: http://getcomposer.org 144 | [3]: https://packagist.org/packages/dflydev/stack-authentication 145 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" 5 | ], 6 | "hash": "5a683e7e04d9c6771a4a41ea92d0cea9", 7 | "packages": [ 8 | { 9 | "name": "psr/log", 10 | "version": "1.0.0", 11 | "source": { 12 | "type": "git", 13 | "url": "https://github.com/php-fig/log", 14 | "reference": "1.0.0" 15 | }, 16 | "dist": { 17 | "type": "zip", 18 | "url": "https://github.com/php-fig/log/archive/1.0.0.zip", 19 | "reference": "1.0.0", 20 | "shasum": "" 21 | }, 22 | "type": "library", 23 | "autoload": { 24 | "psr-0": { 25 | "Psr\\Log\\": "" 26 | } 27 | }, 28 | "notification-url": "https://packagist.org/downloads/", 29 | "license": [ 30 | "MIT" 31 | ], 32 | "authors": [ 33 | { 34 | "name": "PHP-FIG", 35 | "homepage": "http://www.php-fig.org/" 36 | } 37 | ], 38 | "description": "Common interface for logging libraries", 39 | "keywords": [ 40 | "log", 41 | "psr", 42 | "psr-3" 43 | ], 44 | "time": "2012-12-21 11:40:51" 45 | }, 46 | { 47 | "name": "symfony/debug", 48 | "version": "v2.3.2", 49 | "target-dir": "Symfony/Component/Debug", 50 | "source": { 51 | "type": "git", 52 | "url": "https://github.com/symfony/Debug.git", 53 | "reference": "v2.3.2" 54 | }, 55 | "dist": { 56 | "type": "zip", 57 | "url": "https://api.github.com/repos/symfony/Debug/zipball/v2.3.2", 58 | "reference": "v2.3.2", 59 | "shasum": "" 60 | }, 61 | "require": { 62 | "php": ">=5.3.3" 63 | }, 64 | "require-dev": { 65 | "symfony/http-foundation": "~2.1", 66 | "symfony/http-kernel": "~2.1" 67 | }, 68 | "suggest": { 69 | "symfony/class-loader": "", 70 | "symfony/http-foundation": "", 71 | "symfony/http-kernel": "" 72 | }, 73 | "type": "library", 74 | "extra": { 75 | "branch-alias": { 76 | "dev-master": "2.3-dev" 77 | } 78 | }, 79 | "autoload": { 80 | "psr-0": { 81 | "Symfony\\Component\\Debug\\": "" 82 | } 83 | }, 84 | "notification-url": "https://packagist.org/downloads/", 85 | "license": [ 86 | "MIT" 87 | ], 88 | "authors": [ 89 | { 90 | "name": "Fabien Potencier", 91 | "email": "fabien@symfony.com" 92 | }, 93 | { 94 | "name": "Symfony Community", 95 | "homepage": "http://symfony.com/contributors" 96 | } 97 | ], 98 | "description": "Symfony Debug Component", 99 | "homepage": "http://symfony.com", 100 | "time": "2013-07-01 12:24:43" 101 | }, 102 | { 103 | "name": "symfony/event-dispatcher", 104 | "version": "v2.3.2", 105 | "target-dir": "Symfony/Component/EventDispatcher", 106 | "source": { 107 | "type": "git", 108 | "url": "https://github.com/symfony/EventDispatcher.git", 109 | "reference": "v2.3.2" 110 | }, 111 | "dist": { 112 | "type": "zip", 113 | "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/v2.3.2", 114 | "reference": "v2.3.2", 115 | "shasum": "" 116 | }, 117 | "require": { 118 | "php": ">=5.3.3" 119 | }, 120 | "require-dev": { 121 | "symfony/dependency-injection": "~2.0" 122 | }, 123 | "suggest": { 124 | "symfony/dependency-injection": "", 125 | "symfony/http-kernel": "" 126 | }, 127 | "type": "library", 128 | "extra": { 129 | "branch-alias": { 130 | "dev-master": "2.3-dev" 131 | } 132 | }, 133 | "autoload": { 134 | "psr-0": { 135 | "Symfony\\Component\\EventDispatcher\\": "" 136 | } 137 | }, 138 | "notification-url": "https://packagist.org/downloads/", 139 | "license": [ 140 | "MIT" 141 | ], 142 | "authors": [ 143 | { 144 | "name": "Fabien Potencier", 145 | "email": "fabien@symfony.com" 146 | }, 147 | { 148 | "name": "Symfony Community", 149 | "homepage": "http://symfony.com/contributors" 150 | } 151 | ], 152 | "description": "Symfony EventDispatcher Component", 153 | "homepage": "http://symfony.com", 154 | "time": "2013-05-13 14:36:40" 155 | }, 156 | { 157 | "name": "symfony/http-foundation", 158 | "version": "v2.3.2", 159 | "target-dir": "Symfony/Component/HttpFoundation", 160 | "source": { 161 | "type": "git", 162 | "url": "https://github.com/symfony/HttpFoundation.git", 163 | "reference": "v2.3.2" 164 | }, 165 | "dist": { 166 | "type": "zip", 167 | "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/v2.3.2", 168 | "reference": "v2.3.2", 169 | "shasum": "" 170 | }, 171 | "require": { 172 | "php": ">=5.3.3" 173 | }, 174 | "type": "library", 175 | "extra": { 176 | "branch-alias": { 177 | "dev-master": "2.3-dev" 178 | } 179 | }, 180 | "autoload": { 181 | "psr-0": { 182 | "Symfony\\Component\\HttpFoundation\\": "" 183 | }, 184 | "classmap": [ 185 | "Symfony/Component/HttpFoundation/Resources/stubs" 186 | ] 187 | }, 188 | "notification-url": "https://packagist.org/downloads/", 189 | "license": [ 190 | "MIT" 191 | ], 192 | "authors": [ 193 | { 194 | "name": "Fabien Potencier", 195 | "email": "fabien@symfony.com" 196 | }, 197 | { 198 | "name": "Symfony Community", 199 | "homepage": "http://symfony.com/contributors" 200 | } 201 | ], 202 | "description": "Symfony HttpFoundation Component", 203 | "homepage": "http://symfony.com", 204 | "time": "2013-07-17 05:57:53" 205 | }, 206 | { 207 | "name": "symfony/http-kernel", 208 | "version": "v2.3.2", 209 | "target-dir": "Symfony/Component/HttpKernel", 210 | "source": { 211 | "type": "git", 212 | "url": "https://github.com/symfony/HttpKernel.git", 213 | "reference": "v2.3.2" 214 | }, 215 | "dist": { 216 | "type": "zip", 217 | "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/v2.3.2", 218 | "reference": "v2.3.2", 219 | "shasum": "" 220 | }, 221 | "require": { 222 | "php": ">=5.3.3", 223 | "psr/log": "~1.0", 224 | "symfony/debug": "~2.3", 225 | "symfony/event-dispatcher": "~2.1", 226 | "symfony/http-foundation": "~2.2" 227 | }, 228 | "require-dev": { 229 | "symfony/browser-kit": "2.2.*", 230 | "symfony/class-loader": "~2.1", 231 | "symfony/config": "~2.0", 232 | "symfony/console": "2.2.*", 233 | "symfony/dependency-injection": "~2.0", 234 | "symfony/finder": "~2.0", 235 | "symfony/process": "~2.0", 236 | "symfony/routing": "~2.2", 237 | "symfony/stopwatch": "~2.2" 238 | }, 239 | "suggest": { 240 | "symfony/browser-kit": "", 241 | "symfony/class-loader": "", 242 | "symfony/config": "", 243 | "symfony/console": "", 244 | "symfony/dependency-injection": "", 245 | "symfony/finder": "" 246 | }, 247 | "type": "library", 248 | "extra": { 249 | "branch-alias": { 250 | "dev-master": "2.3-dev" 251 | } 252 | }, 253 | "autoload": { 254 | "psr-0": { 255 | "Symfony\\Component\\HttpKernel\\": "" 256 | } 257 | }, 258 | "notification-url": "https://packagist.org/downloads/", 259 | "license": [ 260 | "MIT" 261 | ], 262 | "authors": [ 263 | { 264 | "name": "Fabien Potencier", 265 | "email": "fabien@symfony.com" 266 | }, 267 | { 268 | "name": "Symfony Community", 269 | "homepage": "http://symfony.com/contributors" 270 | } 271 | ], 272 | "description": "Symfony HttpKernel Component", 273 | "homepage": "http://symfony.com", 274 | "time": "2013-07-17 06:22:21" 275 | } 276 | ], 277 | "packages-dev": [ 278 | { 279 | "name": "phpunit/php-code-coverage", 280 | "version": "1.2.12", 281 | "source": { 282 | "type": "git", 283 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 284 | "reference": "1.2.12" 285 | }, 286 | "dist": { 287 | "type": "zip", 288 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/1.2.12", 289 | "reference": "1.2.12", 290 | "shasum": "" 291 | }, 292 | "require": { 293 | "php": ">=5.3.3", 294 | "phpunit/php-file-iterator": ">=1.3.0@stable", 295 | "phpunit/php-text-template": ">=1.1.1@stable", 296 | "phpunit/php-token-stream": ">=1.1.3@stable" 297 | }, 298 | "require-dev": { 299 | "phpunit/phpunit": "3.7.*@dev" 300 | }, 301 | "suggest": { 302 | "ext-dom": "*", 303 | "ext-xdebug": ">=2.0.5" 304 | }, 305 | "type": "library", 306 | "extra": { 307 | "branch-alias": { 308 | "dev-master": "1.2.x-dev" 309 | } 310 | }, 311 | "autoload": { 312 | "classmap": [ 313 | "PHP/" 314 | ] 315 | }, 316 | "notification-url": "https://packagist.org/downloads/", 317 | "include-path": [ 318 | "" 319 | ], 320 | "license": [ 321 | "BSD-3-Clause" 322 | ], 323 | "authors": [ 324 | { 325 | "name": "Sebastian Bergmann", 326 | "email": "sb@sebastian-bergmann.de", 327 | "role": "lead" 328 | } 329 | ], 330 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 331 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 332 | "keywords": [ 333 | "coverage", 334 | "testing", 335 | "xunit" 336 | ], 337 | "time": "2013-07-06 06:26:16" 338 | }, 339 | { 340 | "name": "phpunit/php-file-iterator", 341 | "version": "1.3.3", 342 | "source": { 343 | "type": "git", 344 | "url": "git://github.com/sebastianbergmann/php-file-iterator.git", 345 | "reference": "1.3.3" 346 | }, 347 | "dist": { 348 | "type": "zip", 349 | "url": "https://github.com/sebastianbergmann/php-file-iterator/zipball/1.3.3", 350 | "reference": "1.3.3", 351 | "shasum": "" 352 | }, 353 | "require": { 354 | "php": ">=5.3.3" 355 | }, 356 | "type": "library", 357 | "autoload": { 358 | "classmap": [ 359 | "File/" 360 | ] 361 | }, 362 | "notification-url": "https://packagist.org/downloads/", 363 | "include-path": [ 364 | "" 365 | ], 366 | "license": [ 367 | "BSD-3-Clause" 368 | ], 369 | "authors": [ 370 | { 371 | "name": "Sebastian Bergmann", 372 | "email": "sb@sebastian-bergmann.de", 373 | "role": "lead" 374 | } 375 | ], 376 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 377 | "homepage": "http://www.phpunit.de/", 378 | "keywords": [ 379 | "filesystem", 380 | "iterator" 381 | ], 382 | "time": "2012-10-11 04:44:38" 383 | }, 384 | { 385 | "name": "phpunit/php-text-template", 386 | "version": "1.1.4", 387 | "source": { 388 | "type": "git", 389 | "url": "git://github.com/sebastianbergmann/php-text-template.git", 390 | "reference": "1.1.4" 391 | }, 392 | "dist": { 393 | "type": "zip", 394 | "url": "https://github.com/sebastianbergmann/php-text-template/zipball/1.1.4", 395 | "reference": "1.1.4", 396 | "shasum": "" 397 | }, 398 | "require": { 399 | "php": ">=5.3.3" 400 | }, 401 | "type": "library", 402 | "autoload": { 403 | "classmap": [ 404 | "Text/" 405 | ] 406 | }, 407 | "notification-url": "https://packagist.org/downloads/", 408 | "include-path": [ 409 | "" 410 | ], 411 | "license": [ 412 | "BSD-3-Clause" 413 | ], 414 | "authors": [ 415 | { 416 | "name": "Sebastian Bergmann", 417 | "email": "sb@sebastian-bergmann.de", 418 | "role": "lead" 419 | } 420 | ], 421 | "description": "Simple template engine.", 422 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 423 | "keywords": [ 424 | "template" 425 | ], 426 | "time": "2012-10-31 11:15:28" 427 | }, 428 | { 429 | "name": "phpunit/php-timer", 430 | "version": "1.0.4", 431 | "source": { 432 | "type": "git", 433 | "url": "git://github.com/sebastianbergmann/php-timer.git", 434 | "reference": "1.0.4" 435 | }, 436 | "dist": { 437 | "type": "zip", 438 | "url": "https://github.com/sebastianbergmann/php-timer/zipball/1.0.4", 439 | "reference": "1.0.4", 440 | "shasum": "" 441 | }, 442 | "require": { 443 | "php": ">=5.3.3" 444 | }, 445 | "type": "library", 446 | "autoload": { 447 | "classmap": [ 448 | "PHP/" 449 | ] 450 | }, 451 | "notification-url": "https://packagist.org/downloads/", 452 | "include-path": [ 453 | "" 454 | ], 455 | "license": [ 456 | "BSD-3-Clause" 457 | ], 458 | "authors": [ 459 | { 460 | "name": "Sebastian Bergmann", 461 | "email": "sb@sebastian-bergmann.de", 462 | "role": "lead" 463 | } 464 | ], 465 | "description": "Utility class for timing", 466 | "homepage": "http://www.phpunit.de/", 467 | "keywords": [ 468 | "timer" 469 | ], 470 | "time": "2012-10-11 04:45:58" 471 | }, 472 | { 473 | "name": "phpunit/php-token-stream", 474 | "version": "1.1.7", 475 | "source": { 476 | "type": "git", 477 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 478 | "reference": "1.1.7" 479 | }, 480 | "dist": { 481 | "type": "zip", 482 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1.1.7", 483 | "reference": "1.1.7", 484 | "shasum": "" 485 | }, 486 | "require": { 487 | "ext-tokenizer": "*", 488 | "php": ">=5.3.3" 489 | }, 490 | "type": "library", 491 | "autoload": { 492 | "classmap": [ 493 | "PHP/" 494 | ] 495 | }, 496 | "notification-url": "https://packagist.org/downloads/", 497 | "include-path": [ 498 | "" 499 | ], 500 | "license": [ 501 | "BSD-3-Clause" 502 | ], 503 | "authors": [ 504 | { 505 | "name": "Sebastian Bergmann", 506 | "email": "sb@sebastian-bergmann.de", 507 | "role": "lead" 508 | } 509 | ], 510 | "description": "Wrapper around PHP's tokenizer extension.", 511 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 512 | "keywords": [ 513 | "tokenizer" 514 | ], 515 | "time": "2013-07-29 14:27:06" 516 | }, 517 | { 518 | "name": "phpunit/phpunit", 519 | "version": "3.7.21", 520 | "source": { 521 | "type": "git", 522 | "url": "https://github.com/sebastianbergmann/phpunit.git", 523 | "reference": "3.7.21" 524 | }, 525 | "dist": { 526 | "type": "zip", 527 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3.7.21", 528 | "reference": "3.7.21", 529 | "shasum": "" 530 | }, 531 | "require": { 532 | "ext-dom": "*", 533 | "ext-pcre": "*", 534 | "ext-reflection": "*", 535 | "ext-spl": "*", 536 | "php": ">=5.3.3", 537 | "phpunit/php-code-coverage": ">=1.2.1,<1.3.0", 538 | "phpunit/php-file-iterator": ">=1.3.1", 539 | "phpunit/php-text-template": ">=1.1.1", 540 | "phpunit/php-timer": ">=1.0.2,<1.1.0", 541 | "phpunit/phpunit-mock-objects": ">=1.2.0,<1.3.0", 542 | "symfony/yaml": ">=2.0,<3.0" 543 | }, 544 | "require-dev": { 545 | "pear-pear/pear": "1.9.4" 546 | }, 547 | "suggest": { 548 | "ext-json": "*", 549 | "ext-simplexml": "*", 550 | "ext-tokenizer": "*", 551 | "phpunit/php-invoker": ">=1.1.0,<1.2.0" 552 | }, 553 | "bin": [ 554 | "composer/bin/phpunit" 555 | ], 556 | "type": "library", 557 | "extra": { 558 | "branch-alias": { 559 | "dev-master": "3.7.x-dev" 560 | } 561 | }, 562 | "autoload": { 563 | "classmap": [ 564 | "PHPUnit/" 565 | ] 566 | }, 567 | "notification-url": "https://packagist.org/downloads/", 568 | "include-path": [ 569 | "", 570 | "../../symfony/yaml/" 571 | ], 572 | "license": [ 573 | "BSD-3-Clause" 574 | ], 575 | "authors": [ 576 | { 577 | "name": "Sebastian Bergmann", 578 | "email": "sebastian@phpunit.de", 579 | "role": "lead" 580 | } 581 | ], 582 | "description": "The PHP Unit Testing framework.", 583 | "homepage": "http://www.phpunit.de/", 584 | "keywords": [ 585 | "phpunit", 586 | "testing", 587 | "xunit" 588 | ], 589 | "time": "2013-05-23 18:54:29" 590 | }, 591 | { 592 | "name": "phpunit/phpunit-mock-objects", 593 | "version": "1.2.3", 594 | "source": { 595 | "type": "git", 596 | "url": "git://github.com/sebastianbergmann/phpunit-mock-objects.git", 597 | "reference": "1.2.3" 598 | }, 599 | "dist": { 600 | "type": "zip", 601 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects/archive/1.2.3.zip", 602 | "reference": "1.2.3", 603 | "shasum": "" 604 | }, 605 | "require": { 606 | "php": ">=5.3.3", 607 | "phpunit/php-text-template": ">=1.1.1@stable" 608 | }, 609 | "suggest": { 610 | "ext-soap": "*" 611 | }, 612 | "type": "library", 613 | "autoload": { 614 | "classmap": [ 615 | "PHPUnit/" 616 | ] 617 | }, 618 | "notification-url": "https://packagist.org/downloads/", 619 | "include-path": [ 620 | "" 621 | ], 622 | "license": [ 623 | "BSD-3-Clause" 624 | ], 625 | "authors": [ 626 | { 627 | "name": "Sebastian Bergmann", 628 | "email": "sb@sebastian-bergmann.de", 629 | "role": "lead" 630 | } 631 | ], 632 | "description": "Mock Object library for PHPUnit", 633 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 634 | "keywords": [ 635 | "mock", 636 | "xunit" 637 | ], 638 | "time": "2013-01-13 10:24:48" 639 | }, 640 | { 641 | "name": "pimple/pimple", 642 | "version": "v1.0.2", 643 | "source": { 644 | "type": "git", 645 | "url": "https://github.com/fabpot/Pimple.git", 646 | "reference": "v1.0.2" 647 | }, 648 | "dist": { 649 | "type": "zip", 650 | "url": "https://api.github.com/repos/fabpot/Pimple/zipball/v1.0.2", 651 | "reference": "v1.0.2", 652 | "shasum": "" 653 | }, 654 | "require": { 655 | "php": ">=5.3.0" 656 | }, 657 | "type": "library", 658 | "extra": { 659 | "branch-alias": { 660 | "dev-master": "1.0.x-dev" 661 | } 662 | }, 663 | "autoload": { 664 | "psr-0": { 665 | "Pimple": "lib/" 666 | } 667 | }, 668 | "notification-url": "https://packagist.org/downloads/", 669 | "license": [ 670 | "MIT" 671 | ], 672 | "authors": [ 673 | { 674 | "name": "Fabien Potencier", 675 | "email": "fabien@symfony.com" 676 | } 677 | ], 678 | "description": "Pimple is a simple Dependency Injection Container for PHP 5.3", 679 | "homepage": "http://pimple.sensiolabs.org", 680 | "keywords": [ 681 | "container", 682 | "dependency injection" 683 | ], 684 | "time": "2013-03-08 08:21:40" 685 | }, 686 | { 687 | "name": "silex/silex", 688 | "version": "dev-master", 689 | "source": { 690 | "type": "git", 691 | "url": "https://github.com/fabpot/Silex.git", 692 | "reference": "e9bedd65873d6e20e2dd9eee9cde4723f10bcdb0" 693 | }, 694 | "dist": { 695 | "type": "zip", 696 | "url": "https://api.github.com/repos/fabpot/Silex/zipball/e9bedd65873d6e20e2dd9eee9cde4723f10bcdb0", 697 | "reference": "e9bedd65873d6e20e2dd9eee9cde4723f10bcdb0", 698 | "shasum": "" 699 | }, 700 | "require": { 701 | "php": ">=5.3.3", 702 | "pimple/pimple": "1.*", 703 | "symfony/event-dispatcher": ">=2.3,<2.4-dev", 704 | "symfony/http-foundation": ">=2.3,<2.4-dev", 705 | "symfony/http-kernel": ">=2.3,<2.4-dev", 706 | "symfony/routing": ">=2.3,<2.4-dev" 707 | }, 708 | "require-dev": { 709 | "doctrine/dbal": ">=2.2.0,<2.4.0-dev", 710 | "monolog/monolog": "~1.4,>=1.4.1", 711 | "phpunit/phpunit": "~3.7", 712 | "swiftmailer/swiftmailer": "5.*", 713 | "symfony/browser-kit": ">=2.3,<2.4-dev", 714 | "symfony/config": ">=2.3,<2.4-dev", 715 | "symfony/css-selector": ">=2.3,<2.4-dev", 716 | "symfony/dom-crawler": ">=2.3,<2.4-dev", 717 | "symfony/finder": ">=2.3,<2.4-dev", 718 | "symfony/form": ">=2.3,<2.4-dev", 719 | "symfony/locale": ">=2.3,<2.4-dev", 720 | "symfony/monolog-bridge": ">=2.3,<2.4-dev", 721 | "symfony/options-resolver": ">=2.3,<2.4-dev", 722 | "symfony/process": ">=2.3,<2.4-dev", 723 | "symfony/security": ">=2.3,<2.4-dev", 724 | "symfony/serializer": ">=2.3,<2.4-dev", 725 | "symfony/translation": ">=2.3,<2.4-dev", 726 | "symfony/twig-bridge": ">=2.3,<2.4-dev", 727 | "symfony/validator": ">=2.3,<2.4-dev", 728 | "twig/twig": ">=1.8.0,<2.0-dev" 729 | }, 730 | "suggest": { 731 | "symfony/browser-kit": ">=2.3,<2.4-dev", 732 | "symfony/css-selector": ">=2.3,<2.4-dev", 733 | "symfony/dom-crawler": ">=2.3,<2.4-dev", 734 | "symfony/form": ">=2.3,<2.4-dev" 735 | }, 736 | "type": "library", 737 | "extra": { 738 | "branch-alias": { 739 | "dev-master": "1.1.x-dev" 740 | } 741 | }, 742 | "autoload": { 743 | "psr-0": { 744 | "Silex": "src/" 745 | } 746 | }, 747 | "notification-url": "https://packagist.org/downloads/", 748 | "license": [ 749 | "MIT" 750 | ], 751 | "authors": [ 752 | { 753 | "name": "Fabien Potencier", 754 | "email": "fabien@symfony.com" 755 | }, 756 | { 757 | "name": "Igor Wiedler", 758 | "email": "igor@wiedler.ch", 759 | "homepage": "http://wiedler.ch/igor/" 760 | } 761 | ], 762 | "description": "The PHP micro-framework based on the Symfony2 Components", 763 | "homepage": "http://silex.sensiolabs.org", 764 | "keywords": [ 765 | "microframework" 766 | ], 767 | "time": "2013-07-27 05:29:38" 768 | }, 769 | { 770 | "name": "stack/builder", 771 | "version": "dev-master", 772 | "source": { 773 | "type": "git", 774 | "url": "https://github.com/stackphp/builder.git", 775 | "reference": "d438b2aeb1f3dfa2c16497c68b7016ab7998748d" 776 | }, 777 | "dist": { 778 | "type": "zip", 779 | "url": "https://api.github.com/repos/stackphp/builder/zipball/d438b2aeb1f3dfa2c16497c68b7016ab7998748d", 780 | "reference": "d438b2aeb1f3dfa2c16497c68b7016ab7998748d", 781 | "shasum": "" 782 | }, 783 | "require": { 784 | "php": ">=5.4.0", 785 | "symfony/http-foundation": "~2.1", 786 | "symfony/http-kernel": "~2.1" 787 | }, 788 | "require-dev": { 789 | "silex/silex": "1.0.*@dev" 790 | }, 791 | "type": "library", 792 | "extra": { 793 | "branch-alias": { 794 | "dev-master": "1.0-dev" 795 | } 796 | }, 797 | "autoload": { 798 | "psr-0": { 799 | "Stack": "src" 800 | } 801 | }, 802 | "notification-url": "https://packagist.org/downloads/", 803 | "license": [ 804 | "MIT" 805 | ], 806 | "authors": [ 807 | { 808 | "name": "Igor Wiedler", 809 | "email": "igor@wiedler.ch", 810 | "homepage": "http://wiedler.ch/igor/" 811 | } 812 | ], 813 | "description": "Builder for stack middlewares based on HttpKernelInterface.", 814 | "keywords": [ 815 | "stack" 816 | ], 817 | "time": "2013-04-29 12:20:08" 818 | }, 819 | { 820 | "name": "stack/callable-http-kernel", 821 | "version": "dev-master", 822 | "source": { 823 | "type": "git", 824 | "url": "https://github.com/stackphp/CallableHttpKernel.git", 825 | "reference": "2cea2eab2c3a618bd378f1a2fa05917cf934b518" 826 | }, 827 | "dist": { 828 | "type": "zip", 829 | "url": "https://api.github.com/repos/stackphp/CallableHttpKernel/zipball/2cea2eab2c3a618bd378f1a2fa05917cf934b518", 830 | "reference": "2cea2eab2c3a618bd378f1a2fa05917cf934b518", 831 | "shasum": "" 832 | }, 833 | "require": { 834 | "php": ">=5.4.0", 835 | "symfony/http-foundation": "~2.1", 836 | "symfony/http-kernel": "~2.1" 837 | }, 838 | "type": "library", 839 | "extra": { 840 | "branch-alias": { 841 | "dev-master": "1.0-dev" 842 | } 843 | }, 844 | "autoload": { 845 | "psr-0": { 846 | "Stack": "src" 847 | } 848 | }, 849 | "notification-url": "https://packagist.org/downloads/", 850 | "license": [ 851 | "MIT" 852 | ], 853 | "authors": [ 854 | { 855 | "name": "Igor Wiedler", 856 | "email": "igor@wiedler.ch", 857 | "homepage": "http://wiedler.ch/igor/" 858 | } 859 | ], 860 | "description": "HttpKernelInterface implementation based on callables.", 861 | "keywords": [ 862 | "stack" 863 | ], 864 | "time": "2013-05-17 16:07:54" 865 | }, 866 | { 867 | "name": "stack/inline", 868 | "version": "dev-master", 869 | "source": { 870 | "type": "git", 871 | "url": "https://github.com/stackphp/inline.git", 872 | "reference": "31d8ca1efaa8680c20bc3229e441c8733ce84899" 873 | }, 874 | "dist": { 875 | "type": "zip", 876 | "url": "https://api.github.com/repos/stackphp/inline/zipball/31d8ca1efaa8680c20bc3229e441c8733ce84899", 877 | "reference": "31d8ca1efaa8680c20bc3229e441c8733ce84899", 878 | "shasum": "" 879 | }, 880 | "require": { 881 | "php": ">=5.4.0", 882 | "symfony/http-foundation": "~2.1", 883 | "symfony/http-kernel": "~2.1" 884 | }, 885 | "require-dev": { 886 | "silex/silex": "~1.0@dev", 887 | "stack/builder": "~1.0@dev", 888 | "stack/callable-http-kernel": "~1.0@dev" 889 | }, 890 | "type": "library", 891 | "extra": { 892 | "branch-alias": { 893 | "dev-master": "1.0-dev" 894 | } 895 | }, 896 | "autoload": { 897 | "psr-0": { 898 | "Stack": "src" 899 | } 900 | }, 901 | "notification-url": "https://packagist.org/downloads/", 902 | "license": [ 903 | "MIT" 904 | ], 905 | "authors": [ 906 | { 907 | "name": "Igor Wiedler", 908 | "email": "igor@wiedler.ch", 909 | "homepage": "http://wiedler.ch/igor/" 910 | } 911 | ], 912 | "description": "Inline stack middleware.", 913 | "keywords": [ 914 | "callable", 915 | "inline", 916 | "stack" 917 | ], 918 | "time": "2013-04-09 15:57:37" 919 | }, 920 | { 921 | "name": "symfony/browser-kit", 922 | "version": "v2.3.2", 923 | "target-dir": "Symfony/Component/BrowserKit", 924 | "source": { 925 | "type": "git", 926 | "url": "https://github.com/symfony/BrowserKit.git", 927 | "reference": "v2.3.2" 928 | }, 929 | "dist": { 930 | "type": "zip", 931 | "url": "https://api.github.com/repos/symfony/BrowserKit/zipball/v2.3.2", 932 | "reference": "v2.3.2", 933 | "shasum": "" 934 | }, 935 | "require": { 936 | "php": ">=5.3.3", 937 | "symfony/dom-crawler": "~2.0" 938 | }, 939 | "require-dev": { 940 | "symfony/css-selector": "~2.0", 941 | "symfony/process": "~2.0" 942 | }, 943 | "suggest": { 944 | "symfony/process": "" 945 | }, 946 | "type": "library", 947 | "extra": { 948 | "branch-alias": { 949 | "dev-master": "2.3-dev" 950 | } 951 | }, 952 | "autoload": { 953 | "psr-0": { 954 | "Symfony\\Component\\BrowserKit\\": "" 955 | } 956 | }, 957 | "notification-url": "https://packagist.org/downloads/", 958 | "license": [ 959 | "MIT" 960 | ], 961 | "authors": [ 962 | { 963 | "name": "Fabien Potencier", 964 | "email": "fabien@symfony.com" 965 | }, 966 | { 967 | "name": "Symfony Community", 968 | "homepage": "http://symfony.com/contributors" 969 | } 970 | ], 971 | "description": "Symfony BrowserKit Component", 972 | "homepage": "http://symfony.com", 973 | "time": "2013-07-07 15:48:29" 974 | }, 975 | { 976 | "name": "symfony/dom-crawler", 977 | "version": "v2.3.2", 978 | "target-dir": "Symfony/Component/DomCrawler", 979 | "source": { 980 | "type": "git", 981 | "url": "https://github.com/symfony/DomCrawler.git", 982 | "reference": "v2.3.2" 983 | }, 984 | "dist": { 985 | "type": "zip", 986 | "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/v2.3.2", 987 | "reference": "v2.3.2", 988 | "shasum": "" 989 | }, 990 | "require": { 991 | "php": ">=5.3.3" 992 | }, 993 | "require-dev": { 994 | "symfony/css-selector": "~2.0" 995 | }, 996 | "suggest": { 997 | "symfony/css-selector": "" 998 | }, 999 | "type": "library", 1000 | "extra": { 1001 | "branch-alias": { 1002 | "dev-master": "2.3-dev" 1003 | } 1004 | }, 1005 | "autoload": { 1006 | "psr-0": { 1007 | "Symfony\\Component\\DomCrawler\\": "" 1008 | } 1009 | }, 1010 | "notification-url": "https://packagist.org/downloads/", 1011 | "license": [ 1012 | "MIT" 1013 | ], 1014 | "authors": [ 1015 | { 1016 | "name": "Fabien Potencier", 1017 | "email": "fabien@symfony.com" 1018 | }, 1019 | { 1020 | "name": "Symfony Community", 1021 | "homepage": "http://symfony.com/contributors" 1022 | } 1023 | ], 1024 | "description": "Symfony DomCrawler Component", 1025 | "homepage": "http://symfony.com", 1026 | "time": "2013-07-01 12:24:43" 1027 | }, 1028 | { 1029 | "name": "symfony/routing", 1030 | "version": "v2.3.2", 1031 | "target-dir": "Symfony/Component/Routing", 1032 | "source": { 1033 | "type": "git", 1034 | "url": "https://github.com/symfony/Routing.git", 1035 | "reference": "v2.3.2" 1036 | }, 1037 | "dist": { 1038 | "type": "zip", 1039 | "url": "https://api.github.com/repos/symfony/Routing/zipball/v2.3.2", 1040 | "reference": "v2.3.2", 1041 | "shasum": "" 1042 | }, 1043 | "require": { 1044 | "php": ">=5.3.3" 1045 | }, 1046 | "require-dev": { 1047 | "doctrine/common": "~2.2", 1048 | "psr/log": "~1.0", 1049 | "symfony/config": "~2.2", 1050 | "symfony/yaml": "~2.0" 1051 | }, 1052 | "suggest": { 1053 | "doctrine/common": "", 1054 | "symfony/config": "", 1055 | "symfony/yaml": "" 1056 | }, 1057 | "type": "library", 1058 | "extra": { 1059 | "branch-alias": { 1060 | "dev-master": "2.3-dev" 1061 | } 1062 | }, 1063 | "autoload": { 1064 | "psr-0": { 1065 | "Symfony\\Component\\Routing\\": "" 1066 | } 1067 | }, 1068 | "notification-url": "https://packagist.org/downloads/", 1069 | "license": [ 1070 | "MIT" 1071 | ], 1072 | "authors": [ 1073 | { 1074 | "name": "Fabien Potencier", 1075 | "email": "fabien@symfony.com" 1076 | }, 1077 | { 1078 | "name": "Symfony Community", 1079 | "homepage": "http://symfony.com/contributors" 1080 | } 1081 | ], 1082 | "description": "Symfony Routing Component", 1083 | "homepage": "http://symfony.com", 1084 | "time": "2013-06-23 08:16:02" 1085 | }, 1086 | { 1087 | "name": "symfony/yaml", 1088 | "version": "v2.3.2", 1089 | "target-dir": "Symfony/Component/Yaml", 1090 | "source": { 1091 | "type": "git", 1092 | "url": "https://github.com/symfony/Yaml.git", 1093 | "reference": "v2.3.2" 1094 | }, 1095 | "dist": { 1096 | "type": "zip", 1097 | "url": "https://api.github.com/repos/symfony/Yaml/zipball/v2.3.2", 1098 | "reference": "v2.3.2", 1099 | "shasum": "" 1100 | }, 1101 | "require": { 1102 | "php": ">=5.3.3" 1103 | }, 1104 | "type": "library", 1105 | "extra": { 1106 | "branch-alias": { 1107 | "dev-master": "2.3-dev" 1108 | } 1109 | }, 1110 | "autoload": { 1111 | "psr-0": { 1112 | "Symfony\\Component\\Yaml\\": "" 1113 | } 1114 | }, 1115 | "notification-url": "https://packagist.org/downloads/", 1116 | "license": [ 1117 | "MIT" 1118 | ], 1119 | "authors": [ 1120 | { 1121 | "name": "Fabien Potencier", 1122 | "email": "fabien@symfony.com" 1123 | }, 1124 | { 1125 | "name": "Symfony Community", 1126 | "homepage": "http://symfony.com/contributors" 1127 | } 1128 | ], 1129 | "description": "Symfony Yaml Component", 1130 | "homepage": "http://symfony.com", 1131 | "time": "2013-07-11 19:36:36" 1132 | } 1133 | ], 1134 | "aliases": [ 1135 | 1136 | ], 1137 | "minimum-stability": "stable", 1138 | "stability-flags": { 1139 | "silex/silex": 20, 1140 | "stack/builder": 20, 1141 | "stack/callable-http-kernel": 20, 1142 | "stack/inline": 20 1143 | }, 1144 | "platform": { 1145 | "php": ">=5.4.0" 1146 | }, 1147 | "platform-dev": [ 1148 | 1149 | ] 1150 | } 1151 | --------------------------------------------------------------------------------