From de6b3cea70a3bd2400de93d5bb65127061c96584 Mon Sep 17 00:00:00 2001 From: wing328 Date: Wed, 29 Jun 2016 23:24:27 +0800 Subject: [PATCH] fix slim windows path --- .../languages/SlimFrameworkServerCodegen.java | 48 +- .../slim/{SwaggerServer => }/.htaccess | 0 .../slim/{SwaggerServer => }/README.md | 0 .../slim/{SwaggerServer => }/composer.json | 0 .../petstore-security-test/slim/composer.lock | 254 ++++ .../slim/{SwaggerServer => }/index.php | 0 .../slim/lib/Models/Return.php | 2 +- .../slim/vendor/autoload.php | 7 + .../slim/vendor/composer/ClassLoader.php | 413 ++++++ .../slim/vendor/composer/LICENSE | 21 + .../vendor/composer/autoload_classmap.php | 9 + .../slim/vendor/composer/autoload_files.php | 10 + .../vendor/composer/autoload_namespaces.php | 10 + .../slim/vendor/composer/autoload_psr4.php | 13 + .../slim/vendor/composer/autoload_real.php | 59 + .../slim/vendor/composer/installed.json | 247 ++++ .../container-interop/.gitignore | 3 + .../container-interop/LICENSE | 20 + .../container-interop/README.md | 85 ++ .../container-interop/composer.json | 11 + .../docs/ContainerInterface-meta.md | 114 ++ .../docs/ContainerInterface.md | 153 +++ .../docs/Delegate-lookup-meta.md | 259 ++++ .../container-interop/docs/Delegate-lookup.md | 60 + .../docs/images/interoperating_containers.png | Bin 0 -> 35971 bytes .../docs/images/priority.png | Bin 0 -> 22949 bytes .../docs/images/side_by_side_containers.png | Bin 0 -> 22519 bytes .../Interop/Container/ContainerInterface.php | 37 + .../Exception/ContainerException.php | 13 + .../Container/Exception/NotFoundException.php | 13 + .../slim/vendor/nikic/fast-route/.hhconfig | 1 + .../slim/vendor/nikic/fast-route/.travis.yml | 12 + .../vendor/nikic/fast-route/FastRoute.hhi | 126 ++ .../slim/vendor/nikic/fast-route/LICENSE | 31 + .../slim/vendor/nikic/fast-route/README.md | 273 ++++ .../vendor/nikic/fast-route/composer.json | 21 + .../slim/vendor/nikic/fast-route/phpunit.xml | 24 + .../fast-route/src/BadRouteException.php | 6 + .../nikic/fast-route/src/DataGenerator.php | 25 + .../src/DataGenerator/CharCountBased.php | 28 + .../src/DataGenerator/GroupCountBased.php | 28 + .../src/DataGenerator/GroupPosBased.php | 25 + .../src/DataGenerator/MarkBased.php | 25 + .../src/DataGenerator/RegexBasedAbstract.php | 144 ++ .../nikic/fast-route/src/Dispatcher.php | 25 + .../src/Dispatcher/CharCountBased.php | 28 + .../src/Dispatcher/GroupCountBased.php | 28 + .../src/Dispatcher/GroupPosBased.php | 30 + .../fast-route/src/Dispatcher/MarkBased.php | 28 + .../src/Dispatcher/RegexBasedAbstract.php | 80 ++ .../vendor/nikic/fast-route/src/Route.php | 38 + .../nikic/fast-route/src/RouteCollector.php | 46 + .../nikic/fast-route/src/RouteParser.php | 36 + .../nikic/fast-route/src/RouteParser/Std.php | 81 ++ .../vendor/nikic/fast-route/src/bootstrap.php | 12 + .../vendor/nikic/fast-route/src/functions.php | 70 + .../test/Dispatcher/CharCountBasedTest.php | 13 + .../test/Dispatcher/DispatcherTest.php | 561 ++++++++ .../test/Dispatcher/GroupCountBasedTest.php | 13 + .../test/Dispatcher/GroupPosBasedTest.php | 13 + .../test/Dispatcher/MarkBasedTest.php | 20 + .../HackTypechecker/HackTypecheckerTest.php | 39 + .../HackTypechecker/fixtures/all_options.php | 29 + .../fixtures/empty_options.php | 11 + .../HackTypechecker/fixtures/no_options.php | 11 + .../fast-route/test/RouteParser/StdTest.php | 147 +++ .../nikic/fast-route/test/bootstrap.php | 11 + .../slim/vendor/pimple/pimple/.gitignore | 3 + .../slim/vendor/pimple/pimple/.travis.yml | 32 + .../slim/vendor/pimple/pimple/CHANGELOG | 35 + .../slim/vendor/pimple/pimple/LICENSE | 19 + .../slim/vendor/pimple/pimple/README.rst | 201 +++ .../slim/vendor/pimple/pimple/composer.json | 25 + .../pimple/pimple/ext/pimple/.gitignore | 30 + .../vendor/pimple/pimple/ext/pimple/README.md | 12 + .../vendor/pimple/pimple/ext/pimple/config.m4 | 63 + .../pimple/pimple/ext/pimple/config.w32 | 13 + .../pimple/pimple/ext/pimple/php_pimple.h | 121 ++ .../vendor/pimple/pimple/ext/pimple/pimple.c | 922 +++++++++++++ .../pimple/pimple/ext/pimple/pimple_compat.h | 81 ++ .../pimple/pimple/ext/pimple/tests/001.phpt | 45 + .../pimple/pimple/ext/pimple/tests/002.phpt | 15 + .../pimple/pimple/ext/pimple/tests/003.phpt | 16 + .../pimple/pimple/ext/pimple/tests/004.phpt | 30 + .../pimple/pimple/ext/pimple/tests/005.phpt | 27 + .../pimple/pimple/ext/pimple/tests/006.phpt | 51 + .../pimple/pimple/ext/pimple/tests/007.phpt | 22 + .../pimple/pimple/ext/pimple/tests/008.phpt | 29 + .../pimple/pimple/ext/pimple/tests/009.phpt | 13 + .../pimple/pimple/ext/pimple/tests/010.phpt | 45 + .../pimple/pimple/ext/pimple/tests/011.phpt | 19 + .../pimple/pimple/ext/pimple/tests/012.phpt | 28 + .../pimple/pimple/ext/pimple/tests/013.phpt | 33 + .../pimple/pimple/ext/pimple/tests/014.phpt | 30 + .../pimple/pimple/ext/pimple/tests/015.phpt | 17 + .../pimple/pimple/ext/pimple/tests/016.phpt | 24 + .../pimple/pimple/ext/pimple/tests/017.phpt | 17 + .../pimple/pimple/ext/pimple/tests/017_1.phpt | 17 + .../pimple/pimple/ext/pimple/tests/018.phpt | 23 + .../pimple/pimple/ext/pimple/tests/019.phpt | 18 + .../pimple/pimple/ext/pimple/tests/bench.phpb | 51 + .../pimple/ext/pimple/tests/bench_shared.phpb | 25 + .../vendor/pimple/pimple/phpunit.xml.dist | 14 + .../pimple/pimple/src/Pimple/Container.php | 282 ++++ .../src/Pimple/ServiceProviderInterface.php | 46 + .../src/Pimple/Tests/Fixtures/Invokable.php | 38 + .../Pimple/Tests/Fixtures/NonInvokable.php | 34 + .../Tests/Fixtures/PimpleServiceProvider.php | 54 + .../src/Pimple/Tests/Fixtures/Service.php | 35 + .../PimpleServiceProviderInterfaceTest.php | 76 ++ .../pimple/src/Pimple/Tests/PimpleTest.php | 440 +++++++ .../slim/vendor/psr/http-message/LICENSE | 19 + .../slim/vendor/psr/http-message/README.md | 13 + .../vendor/psr/http-message/composer.json | 25 + .../psr/http-message/src/MessageInterface.php | 187 +++ .../psr/http-message/src/RequestInterface.php | 129 ++ .../http-message/src/ResponseInterface.php | 68 + .../src/ServerRequestInterface.php | 261 ++++ .../psr/http-message/src/StreamInterface.php | 158 +++ .../src/UploadedFileInterface.php | 123 ++ .../psr/http-message/src/UriInterface.php | 323 +++++ .../slim/vendor/slim/slim/CONTRIBUTING.md | 20 + .../slim/vendor/slim/slim/LICENSE.md | 19 + .../slim/vendor/slim/slim/README.md | 84 ++ .../slim/vendor/slim/slim/Slim/App.php | 644 +++++++++ .../slim/slim/Slim/CallableResolver.php | 87 ++ .../slim/Slim/CallableResolverAwareTrait.php | 47 + .../slim/vendor/slim/slim/Slim/Collection.php | 204 +++ .../slim/vendor/slim/slim/Slim/Container.php | 181 +++ .../slim/Slim/DefaultServicesProvider.php | 204 +++ .../slim/slim/Slim/DeferredCallable.php | 39 + .../Slim/Exception/ContainerException.php | 20 + .../ContainerValueNotFoundException.php | 20 + .../Exception/MethodNotAllowedException.php | 45 + .../slim/Slim/Exception/NotFoundException.php | 14 + .../slim/Slim/Exception/SlimException.php | 69 + .../slim/slim/Slim/Handlers/AbstractError.php | 99 ++ .../slim/Slim/Handlers/AbstractHandler.php | 59 + .../vendor/slim/slim/Slim/Handlers/Error.php | 206 +++ .../slim/slim/Slim/Handlers/NotAllowed.php | 147 +++ .../slim/slim/Slim/Handlers/NotFound.php | 126 ++ .../slim/slim/Slim/Handlers/PhpError.php | 205 +++ .../Handlers/Strategies/RequestResponse.php | 43 + .../Strategies/RequestResponseArgs.php | 42 + .../slim/vendor/slim/slim/Slim/Http/Body.php | 22 + .../vendor/slim/slim/Slim/Http/Cookies.php | 195 +++ .../slim/slim/Slim/Http/Environment.php | 52 + .../vendor/slim/slim/Slim/Http/Headers.php | 222 ++++ .../vendor/slim/slim/Slim/Http/Message.php | 295 +++++ .../vendor/slim/slim/Slim/Http/Request.php | 1156 +++++++++++++++++ .../slim/slim/Slim/Http/RequestBody.php | 27 + .../vendor/slim/slim/Slim/Http/Response.php | 470 +++++++ .../vendor/slim/slim/Slim/Http/Stream.php | 409 ++++++ .../slim/slim/Slim/Http/UploadedFile.php | 327 +++++ .../slim/vendor/slim/slim/Slim/Http/Uri.php | 821 ++++++++++++ .../Interfaces/CallableResolverInterface.php | 27 + .../Slim/Interfaces/CollectionInterface.php | 32 + .../Slim/Interfaces/Http/CookiesInterface.php | 23 + .../Interfaces/Http/EnvironmentInterface.php | 20 + .../Slim/Interfaces/Http/HeadersInterface.php | 24 + .../InvocationStrategyInterface.php | 35 + .../Slim/Interfaces/RouteGroupInterface.php | 46 + .../slim/Slim/Interfaces/RouteInterface.php | 129 ++ .../slim/Slim/Interfaces/RouterInterface.php | 107 ++ .../slim/slim/Slim/MiddlewareAwareTrait.php | 120 ++ .../slim/vendor/slim/slim/Slim/Routable.php | 106 ++ .../slim/vendor/slim/slim/Slim/Route.php | 357 +++++ .../slim/vendor/slim/slim/Slim/RouteGroup.php | 47 + .../slim/vendor/slim/slim/Slim/Router.php | 421 ++++++ .../slim/vendor/slim/slim/composer.json | 57 + .../slim/vendor/slim/slim/example/.htaccess | 12 + .../slim/vendor/slim/slim/example/README.md | 19 + .../slim/vendor/slim/slim/example/index.php | 45 + .../slim/{SwaggerServer => }/.htaccess | 0 samples/server/petstore/slim/LICENSE | 25 + .../slim/{SwaggerServer => }/README.md | 0 .../slim/{SwaggerServer => }/composer.json | 0 samples/server/petstore/slim/composer.lock | 254 ++++ .../slim/{SwaggerServer => }/index.php | 0 .../petstore/slim/lib/Models/ApiResponse.php | 17 + .../petstore/slim/lib/Models/Category.php | 15 + .../server/petstore/slim/lib/Models/Order.php | 23 + .../server/petstore/slim/lib/Models/Pet.php | 23 + .../server/petstore/slim/lib/Models/Tag.php | 15 + .../server/petstore/slim/lib/Models/User.php | 27 + .../server/petstore/slim/vendor/autoload.php | 7 + .../slim/vendor/composer/ClassLoader.php | 413 ++++++ .../petstore/slim/vendor/composer/LICENSE | 21 + .../vendor/composer/autoload_classmap.php | 9 + .../slim/vendor/composer/autoload_files.php | 10 + .../vendor/composer/autoload_namespaces.php | 10 + .../slim/vendor/composer/autoload_psr4.php | 13 + .../slim/vendor/composer/autoload_real.php | 59 + .../slim/vendor/composer/installed.json | 247 ++++ .../container-interop/.gitignore | 3 + .../container-interop/LICENSE | 20 + .../container-interop/README.md | 85 ++ .../container-interop/composer.json | 11 + .../docs/ContainerInterface-meta.md | 114 ++ .../docs/ContainerInterface.md | 153 +++ .../docs/Delegate-lookup-meta.md | 259 ++++ .../container-interop/docs/Delegate-lookup.md | 60 + .../docs/images/interoperating_containers.png | Bin 0 -> 35971 bytes .../docs/images/priority.png | Bin 0 -> 22949 bytes .../docs/images/side_by_side_containers.png | Bin 0 -> 22519 bytes .../Interop/Container/ContainerInterface.php | 37 + .../Exception/ContainerException.php | 13 + .../Container/Exception/NotFoundException.php | 13 + .../slim/vendor/nikic/fast-route/.hhconfig | 1 + .../slim/vendor/nikic/fast-route/.travis.yml | 12 + .../vendor/nikic/fast-route/FastRoute.hhi | 126 ++ .../slim/vendor/nikic/fast-route/LICENSE | 31 + .../slim/vendor/nikic/fast-route/README.md | 273 ++++ .../vendor/nikic/fast-route/composer.json | 21 + .../slim/vendor/nikic/fast-route/phpunit.xml | 24 + .../fast-route/src/BadRouteException.php | 6 + .../nikic/fast-route/src/DataGenerator.php | 25 + .../src/DataGenerator/CharCountBased.php | 28 + .../src/DataGenerator/GroupCountBased.php | 28 + .../src/DataGenerator/GroupPosBased.php | 25 + .../src/DataGenerator/MarkBased.php | 25 + .../src/DataGenerator/RegexBasedAbstract.php | 144 ++ .../nikic/fast-route/src/Dispatcher.php | 25 + .../src/Dispatcher/CharCountBased.php | 28 + .../src/Dispatcher/GroupCountBased.php | 28 + .../src/Dispatcher/GroupPosBased.php | 30 + .../fast-route/src/Dispatcher/MarkBased.php | 28 + .../src/Dispatcher/RegexBasedAbstract.php | 80 ++ .../vendor/nikic/fast-route/src/Route.php | 38 + .../nikic/fast-route/src/RouteCollector.php | 46 + .../nikic/fast-route/src/RouteParser.php | 36 + .../nikic/fast-route/src/RouteParser/Std.php | 81 ++ .../vendor/nikic/fast-route/src/bootstrap.php | 12 + .../vendor/nikic/fast-route/src/functions.php | 70 + .../test/Dispatcher/CharCountBasedTest.php | 13 + .../test/Dispatcher/DispatcherTest.php | 561 ++++++++ .../test/Dispatcher/GroupCountBasedTest.php | 13 + .../test/Dispatcher/GroupPosBasedTest.php | 13 + .../test/Dispatcher/MarkBasedTest.php | 20 + .../HackTypechecker/HackTypecheckerTest.php | 39 + .../HackTypechecker/fixtures/all_options.php | 29 + .../fixtures/empty_options.php | 11 + .../HackTypechecker/fixtures/no_options.php | 11 + .../fast-route/test/RouteParser/StdTest.php | 147 +++ .../nikic/fast-route/test/bootstrap.php | 11 + .../slim/vendor/pimple/pimple/.gitignore | 3 + .../slim/vendor/pimple/pimple/.travis.yml | 32 + .../slim/vendor/pimple/pimple/CHANGELOG | 35 + .../slim/vendor/pimple/pimple/LICENSE | 19 + .../slim/vendor/pimple/pimple/README.rst | 201 +++ .../slim/vendor/pimple/pimple/composer.json | 25 + .../pimple/pimple/ext/pimple/.gitignore | 30 + .../vendor/pimple/pimple/ext/pimple/README.md | 12 + .../vendor/pimple/pimple/ext/pimple/config.m4 | 63 + .../pimple/pimple/ext/pimple/config.w32 | 13 + .../pimple/pimple/ext/pimple/php_pimple.h | 121 ++ .../vendor/pimple/pimple/ext/pimple/pimple.c | 922 +++++++++++++ .../pimple/pimple/ext/pimple/pimple_compat.h | 81 ++ .../pimple/pimple/ext/pimple/tests/001.phpt | 45 + .../pimple/pimple/ext/pimple/tests/002.phpt | 15 + .../pimple/pimple/ext/pimple/tests/003.phpt | 16 + .../pimple/pimple/ext/pimple/tests/004.phpt | 30 + .../pimple/pimple/ext/pimple/tests/005.phpt | 27 + .../pimple/pimple/ext/pimple/tests/006.phpt | 51 + .../pimple/pimple/ext/pimple/tests/007.phpt | 22 + .../pimple/pimple/ext/pimple/tests/008.phpt | 29 + .../pimple/pimple/ext/pimple/tests/009.phpt | 13 + .../pimple/pimple/ext/pimple/tests/010.phpt | 45 + .../pimple/pimple/ext/pimple/tests/011.phpt | 19 + .../pimple/pimple/ext/pimple/tests/012.phpt | 28 + .../pimple/pimple/ext/pimple/tests/013.phpt | 33 + .../pimple/pimple/ext/pimple/tests/014.phpt | 30 + .../pimple/pimple/ext/pimple/tests/015.phpt | 17 + .../pimple/pimple/ext/pimple/tests/016.phpt | 24 + .../pimple/pimple/ext/pimple/tests/017.phpt | 17 + .../pimple/pimple/ext/pimple/tests/017_1.phpt | 17 + .../pimple/pimple/ext/pimple/tests/018.phpt | 23 + .../pimple/pimple/ext/pimple/tests/019.phpt | 18 + .../pimple/pimple/ext/pimple/tests/bench.phpb | 51 + .../pimple/ext/pimple/tests/bench_shared.phpb | 25 + .../vendor/pimple/pimple/phpunit.xml.dist | 14 + .../pimple/pimple/src/Pimple/Container.php | 282 ++++ .../src/Pimple/ServiceProviderInterface.php | 46 + .../src/Pimple/Tests/Fixtures/Invokable.php | 38 + .../Pimple/Tests/Fixtures/NonInvokable.php | 34 + .../Tests/Fixtures/PimpleServiceProvider.php | 54 + .../src/Pimple/Tests/Fixtures/Service.php | 35 + .../PimpleServiceProviderInterfaceTest.php | 76 ++ .../pimple/src/Pimple/Tests/PimpleTest.php | 440 +++++++ .../slim/vendor/psr/http-message/LICENSE | 19 + .../slim/vendor/psr/http-message/README.md | 13 + .../vendor/psr/http-message/composer.json | 25 + .../psr/http-message/src/MessageInterface.php | 187 +++ .../psr/http-message/src/RequestInterface.php | 129 ++ .../http-message/src/ResponseInterface.php | 68 + .../src/ServerRequestInterface.php | 261 ++++ .../psr/http-message/src/StreamInterface.php | 158 +++ .../src/UploadedFileInterface.php | 123 ++ .../psr/http-message/src/UriInterface.php | 323 +++++ .../slim/vendor/slim/slim/CONTRIBUTING.md | 20 + .../petstore/slim/vendor/slim/slim/LICENSE.md | 19 + .../petstore/slim/vendor/slim/slim/README.md | 84 ++ .../slim/vendor/slim/slim/Slim/App.php | 644 +++++++++ .../slim/slim/Slim/CallableResolver.php | 87 ++ .../slim/Slim/CallableResolverAwareTrait.php | 47 + .../slim/vendor/slim/slim/Slim/Collection.php | 204 +++ .../slim/vendor/slim/slim/Slim/Container.php | 181 +++ .../slim/Slim/DefaultServicesProvider.php | 204 +++ .../slim/slim/Slim/DeferredCallable.php | 39 + .../Slim/Exception/ContainerException.php | 20 + .../ContainerValueNotFoundException.php | 20 + .../Exception/MethodNotAllowedException.php | 45 + .../slim/Slim/Exception/NotFoundException.php | 14 + .../slim/Slim/Exception/SlimException.php | 69 + .../slim/slim/Slim/Handlers/AbstractError.php | 99 ++ .../slim/Slim/Handlers/AbstractHandler.php | 59 + .../vendor/slim/slim/Slim/Handlers/Error.php | 206 +++ .../slim/slim/Slim/Handlers/NotAllowed.php | 147 +++ .../slim/slim/Slim/Handlers/NotFound.php | 126 ++ .../slim/slim/Slim/Handlers/PhpError.php | 205 +++ .../Handlers/Strategies/RequestResponse.php | 43 + .../Strategies/RequestResponseArgs.php | 42 + .../slim/vendor/slim/slim/Slim/Http/Body.php | 22 + .../vendor/slim/slim/Slim/Http/Cookies.php | 195 +++ .../slim/slim/Slim/Http/Environment.php | 52 + .../vendor/slim/slim/Slim/Http/Headers.php | 222 ++++ .../vendor/slim/slim/Slim/Http/Message.php | 295 +++++ .../vendor/slim/slim/Slim/Http/Request.php | 1156 +++++++++++++++++ .../slim/slim/Slim/Http/RequestBody.php | 27 + .../vendor/slim/slim/Slim/Http/Response.php | 470 +++++++ .../vendor/slim/slim/Slim/Http/Stream.php | 409 ++++++ .../slim/slim/Slim/Http/UploadedFile.php | 327 +++++ .../slim/vendor/slim/slim/Slim/Http/Uri.php | 821 ++++++++++++ .../Interfaces/CallableResolverInterface.php | 27 + .../Slim/Interfaces/CollectionInterface.php | 32 + .../Slim/Interfaces/Http/CookiesInterface.php | 23 + .../Interfaces/Http/EnvironmentInterface.php | 20 + .../Slim/Interfaces/Http/HeadersInterface.php | 24 + .../InvocationStrategyInterface.php | 35 + .../Slim/Interfaces/RouteGroupInterface.php | 46 + .../slim/Slim/Interfaces/RouteInterface.php | 129 ++ .../slim/Slim/Interfaces/RouterInterface.php | 107 ++ .../slim/slim/Slim/MiddlewareAwareTrait.php | 120 ++ .../slim/vendor/slim/slim/Slim/Routable.php | 106 ++ .../slim/vendor/slim/slim/Slim/Route.php | 357 +++++ .../slim/vendor/slim/slim/Slim/RouteGroup.php | 47 + .../slim/vendor/slim/slim/Slim/Router.php | 421 ++++++ .../slim/vendor/slim/slim/composer.json | 57 + .../slim/vendor/slim/slim/example/.htaccess | 12 + .../slim/vendor/slim/slim/example/README.md | 19 + .../slim/vendor/slim/slim/example/index.php | 45 + 351 files changed, 33537 insertions(+), 6 deletions(-) rename samples/server/petstore-security-test/slim/{SwaggerServer => }/.htaccess (100%) rename samples/server/petstore-security-test/slim/{SwaggerServer => }/README.md (100%) rename samples/server/petstore-security-test/slim/{SwaggerServer => }/composer.json (100%) create mode 100644 samples/server/petstore-security-test/slim/composer.lock rename samples/server/petstore-security-test/slim/{SwaggerServer => }/index.php (100%) rename "samples/server/petstore-security-test/slim/SwaggerServer\\lib\\Models/Return.php" => samples/server/petstore-security-test/slim/lib/Models/Return.php (80%) create mode 100644 samples/server/petstore-security-test/slim/vendor/autoload.php create mode 100644 samples/server/petstore-security-test/slim/vendor/composer/ClassLoader.php create mode 100644 samples/server/petstore-security-test/slim/vendor/composer/LICENSE create mode 100644 samples/server/petstore-security-test/slim/vendor/composer/autoload_classmap.php create mode 100644 samples/server/petstore-security-test/slim/vendor/composer/autoload_files.php create mode 100644 samples/server/petstore-security-test/slim/vendor/composer/autoload_namespaces.php create mode 100644 samples/server/petstore-security-test/slim/vendor/composer/autoload_psr4.php create mode 100644 samples/server/petstore-security-test/slim/vendor/composer/autoload_real.php create mode 100644 samples/server/petstore-security-test/slim/vendor/composer/installed.json create mode 100644 samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/.gitignore create mode 100644 samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/LICENSE create mode 100644 samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/README.md create mode 100644 samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/composer.json create mode 100644 samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/ContainerInterface-meta.md create mode 100644 samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/ContainerInterface.md create mode 100644 samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/Delegate-lookup-meta.md create mode 100644 samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/Delegate-lookup.md create mode 100644 samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/images/interoperating_containers.png create mode 100644 samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/images/priority.png create mode 100644 samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/images/side_by_side_containers.png create mode 100644 samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/src/Interop/Container/ContainerInterface.php create mode 100644 samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/src/Interop/Container/Exception/ContainerException.php create mode 100644 samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/src/Interop/Container/Exception/NotFoundException.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/.hhconfig create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/.travis.yml create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/FastRoute.hhi create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/LICENSE create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/README.md create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/composer.json create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/phpunit.xml create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/BadRouteException.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/DataGenerator.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/DataGenerator/CharCountBased.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/DataGenerator/MarkBased.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/MarkBased.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/RegexBasedAbstract.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Route.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/RouteCollector.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/RouteParser.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/RouteParser/Std.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/bootstrap.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/functions.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/Dispatcher/CharCountBasedTest.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/Dispatcher/DispatcherTest.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/Dispatcher/GroupCountBasedTest.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/Dispatcher/GroupPosBasedTest.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/Dispatcher/MarkBasedTest.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/HackTypechecker/HackTypecheckerTest.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/all_options.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/empty_options.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/no_options.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/RouteParser/StdTest.php create mode 100644 samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/bootstrap.php create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/.gitignore create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/.travis.yml create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/CHANGELOG create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/LICENSE create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/README.rst create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/composer.json create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/.gitignore create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/README.md create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/config.m4 create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/config.w32 create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/php_pimple.h create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/pimple.c create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/pimple_compat.h create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/001.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/002.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/003.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/004.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/005.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/006.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/007.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/008.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/009.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/010.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/011.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/012.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/013.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/014.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/015.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/016.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/017.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/018.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/019.phpt create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/bench.phpb create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/phpunit.xml.dist create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Container.php create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Invokable.php create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/PimpleServiceProvider.php create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php create mode 100644 samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php create mode 100644 samples/server/petstore-security-test/slim/vendor/psr/http-message/LICENSE create mode 100644 samples/server/petstore-security-test/slim/vendor/psr/http-message/README.md create mode 100644 samples/server/petstore-security-test/slim/vendor/psr/http-message/composer.json create mode 100644 samples/server/petstore-security-test/slim/vendor/psr/http-message/src/MessageInterface.php create mode 100644 samples/server/petstore-security-test/slim/vendor/psr/http-message/src/RequestInterface.php create mode 100644 samples/server/petstore-security-test/slim/vendor/psr/http-message/src/ResponseInterface.php create mode 100644 samples/server/petstore-security-test/slim/vendor/psr/http-message/src/ServerRequestInterface.php create mode 100644 samples/server/petstore-security-test/slim/vendor/psr/http-message/src/StreamInterface.php create mode 100644 samples/server/petstore-security-test/slim/vendor/psr/http-message/src/UploadedFileInterface.php create mode 100644 samples/server/petstore-security-test/slim/vendor/psr/http-message/src/UriInterface.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/CONTRIBUTING.md create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/LICENSE.md create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/README.md create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/App.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/CallableResolver.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/CallableResolverAwareTrait.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Collection.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Container.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/DefaultServicesProvider.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/DeferredCallable.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Exception/ContainerException.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Exception/ContainerValueNotFoundException.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Exception/MethodNotAllowedException.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Exception/NotFoundException.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Exception/SlimException.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/AbstractError.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/AbstractHandler.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/Error.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/NotAllowed.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/NotFound.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/PhpError.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Body.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Cookies.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Environment.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Headers.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Message.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Request.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/RequestBody.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Response.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Stream.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/UploadedFile.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Uri.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Interfaces/CallableResolverInterface.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Interfaces/CollectionInterface.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Interfaces/Http/CookiesInterface.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Interfaces/Http/EnvironmentInterface.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Interfaces/Http/HeadersInterface.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Interfaces/InvocationStrategyInterface.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Interfaces/RouteGroupInterface.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Interfaces/RouteInterface.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Interfaces/RouterInterface.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/MiddlewareAwareTrait.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Routable.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Route.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/RouteGroup.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Router.php create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/composer.json create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/example/.htaccess create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/example/README.md create mode 100644 samples/server/petstore-security-test/slim/vendor/slim/slim/example/index.php rename samples/server/petstore/slim/{SwaggerServer => }/.htaccess (100%) rename samples/server/petstore/slim/{SwaggerServer => }/README.md (100%) rename samples/server/petstore/slim/{SwaggerServer => }/composer.json (100%) create mode 100644 samples/server/petstore/slim/composer.lock rename samples/server/petstore/slim/{SwaggerServer => }/index.php (100%) create mode 100644 samples/server/petstore/slim/lib/Models/ApiResponse.php create mode 100644 samples/server/petstore/slim/lib/Models/Category.php create mode 100644 samples/server/petstore/slim/lib/Models/Order.php create mode 100644 samples/server/petstore/slim/lib/Models/Pet.php create mode 100644 samples/server/petstore/slim/lib/Models/Tag.php create mode 100644 samples/server/petstore/slim/lib/Models/User.php create mode 100644 samples/server/petstore/slim/vendor/autoload.php create mode 100644 samples/server/petstore/slim/vendor/composer/ClassLoader.php create mode 100644 samples/server/petstore/slim/vendor/composer/LICENSE create mode 100644 samples/server/petstore/slim/vendor/composer/autoload_classmap.php create mode 100644 samples/server/petstore/slim/vendor/composer/autoload_files.php create mode 100644 samples/server/petstore/slim/vendor/composer/autoload_namespaces.php create mode 100644 samples/server/petstore/slim/vendor/composer/autoload_psr4.php create mode 100644 samples/server/petstore/slim/vendor/composer/autoload_real.php create mode 100644 samples/server/petstore/slim/vendor/composer/installed.json create mode 100644 samples/server/petstore/slim/vendor/container-interop/container-interop/.gitignore create mode 100644 samples/server/petstore/slim/vendor/container-interop/container-interop/LICENSE create mode 100644 samples/server/petstore/slim/vendor/container-interop/container-interop/README.md create mode 100644 samples/server/petstore/slim/vendor/container-interop/container-interop/composer.json create mode 100644 samples/server/petstore/slim/vendor/container-interop/container-interop/docs/ContainerInterface-meta.md create mode 100644 samples/server/petstore/slim/vendor/container-interop/container-interop/docs/ContainerInterface.md create mode 100644 samples/server/petstore/slim/vendor/container-interop/container-interop/docs/Delegate-lookup-meta.md create mode 100644 samples/server/petstore/slim/vendor/container-interop/container-interop/docs/Delegate-lookup.md create mode 100644 samples/server/petstore/slim/vendor/container-interop/container-interop/docs/images/interoperating_containers.png create mode 100644 samples/server/petstore/slim/vendor/container-interop/container-interop/docs/images/priority.png create mode 100644 samples/server/petstore/slim/vendor/container-interop/container-interop/docs/images/side_by_side_containers.png create mode 100644 samples/server/petstore/slim/vendor/container-interop/container-interop/src/Interop/Container/ContainerInterface.php create mode 100644 samples/server/petstore/slim/vendor/container-interop/container-interop/src/Interop/Container/Exception/ContainerException.php create mode 100644 samples/server/petstore/slim/vendor/container-interop/container-interop/src/Interop/Container/Exception/NotFoundException.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/.hhconfig create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/.travis.yml create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/FastRoute.hhi create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/LICENSE create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/README.md create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/composer.json create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/phpunit.xml create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/src/BadRouteException.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/src/DataGenerator.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/src/DataGenerator/CharCountBased.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/src/DataGenerator/MarkBased.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/MarkBased.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/RegexBasedAbstract.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/src/Route.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/src/RouteCollector.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/src/RouteParser.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/src/RouteParser/Std.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/src/bootstrap.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/src/functions.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/test/Dispatcher/CharCountBasedTest.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/test/Dispatcher/DispatcherTest.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/test/Dispatcher/GroupCountBasedTest.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/test/Dispatcher/GroupPosBasedTest.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/test/Dispatcher/MarkBasedTest.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/test/HackTypechecker/HackTypecheckerTest.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/all_options.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/empty_options.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/no_options.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/test/RouteParser/StdTest.php create mode 100644 samples/server/petstore/slim/vendor/nikic/fast-route/test/bootstrap.php create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/.gitignore create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/.travis.yml create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/CHANGELOG create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/LICENSE create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/README.rst create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/composer.json create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/.gitignore create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/README.md create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/config.m4 create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/config.w32 create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/php_pimple.h create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/pimple.c create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/pimple_compat.h create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/001.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/002.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/003.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/004.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/005.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/006.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/007.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/008.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/009.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/010.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/011.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/012.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/013.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/014.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/015.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/016.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/017.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/018.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/019.phpt create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/bench.phpb create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/phpunit.xml.dist create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Container.php create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Invokable.php create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/PimpleServiceProvider.php create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php create mode 100644 samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php create mode 100644 samples/server/petstore/slim/vendor/psr/http-message/LICENSE create mode 100644 samples/server/petstore/slim/vendor/psr/http-message/README.md create mode 100644 samples/server/petstore/slim/vendor/psr/http-message/composer.json create mode 100644 samples/server/petstore/slim/vendor/psr/http-message/src/MessageInterface.php create mode 100644 samples/server/petstore/slim/vendor/psr/http-message/src/RequestInterface.php create mode 100644 samples/server/petstore/slim/vendor/psr/http-message/src/ResponseInterface.php create mode 100644 samples/server/petstore/slim/vendor/psr/http-message/src/ServerRequestInterface.php create mode 100644 samples/server/petstore/slim/vendor/psr/http-message/src/StreamInterface.php create mode 100644 samples/server/petstore/slim/vendor/psr/http-message/src/UploadedFileInterface.php create mode 100644 samples/server/petstore/slim/vendor/psr/http-message/src/UriInterface.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/CONTRIBUTING.md create mode 100644 samples/server/petstore/slim/vendor/slim/slim/LICENSE.md create mode 100644 samples/server/petstore/slim/vendor/slim/slim/README.md create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/App.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/CallableResolver.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/CallableResolverAwareTrait.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Collection.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Container.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/DefaultServicesProvider.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/DeferredCallable.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Exception/ContainerException.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Exception/ContainerValueNotFoundException.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Exception/MethodNotAllowedException.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Exception/NotFoundException.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Exception/SlimException.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/AbstractError.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/AbstractHandler.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/Error.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/NotAllowed.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/NotFound.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/PhpError.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Body.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Cookies.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Environment.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Headers.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Message.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Request.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Http/RequestBody.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Response.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Stream.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Http/UploadedFile.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Uri.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Interfaces/CallableResolverInterface.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Interfaces/CollectionInterface.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Interfaces/Http/CookiesInterface.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Interfaces/Http/EnvironmentInterface.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Interfaces/Http/HeadersInterface.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Interfaces/InvocationStrategyInterface.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Interfaces/RouteGroupInterface.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Interfaces/RouteInterface.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Interfaces/RouterInterface.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/MiddlewareAwareTrait.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Routable.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Route.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/RouteGroup.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/Slim/Router.php create mode 100644 samples/server/petstore/slim/vendor/slim/slim/composer.json create mode 100644 samples/server/petstore/slim/vendor/slim/slim/example/.htaccess create mode 100644 samples/server/petstore/slim/vendor/slim/slim/example/README.md create mode 100644 samples/server/petstore/slim/vendor/slim/slim/example/index.php diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SlimFrameworkServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SlimFrameworkServerCodegen.java index 83cd13df968f..1a21b6609d81 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SlimFrameworkServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SlimFrameworkServerCodegen.java @@ -14,12 +14,17 @@ import java.io.File; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.regex.Matcher; public class SlimFrameworkServerCodegen extends DefaultCodegen implements CodegenConfig { protected String invokerPackage; + protected String srcBasePath = "lib"; protected String groupId = "io.swagger"; protected String artifactId = "swagger-server"; protected String artifactVersion = "1.0.0"; + protected String packagePath = ""; // empty packagePath (top folder) + + private String variableNamingConvention = "camelCase"; public SlimFrameworkServerCodegen() { @@ -27,10 +32,10 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege invokerPackage = camelize("SwaggerServer"); - String packagePath = "SwaggerServer"; + //String packagePath = "SwaggerServer"; - modelPackage = packagePath + "\\lib\\Models"; - apiPackage = packagePath + "\\lib"; + modelPackage = packagePath + "\\Models"; + apiPackage = packagePath; outputFolder = "generated-code" + File.separator + "slim"; modelTemplateFiles.put("model.mustache", ".php"); @@ -115,12 +120,12 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege @Override public String apiFileFolder() { - return (outputFolder + "/" + apiPackage()).replace('/', File.separatorChar); + return (outputFolder + "/" + toPackagePath(apiPackage, srcBasePath)); } @Override public String modelFileFolder() { - return (outputFolder + "/" + modelPackage()).replace('/', File.separatorChar); + return (outputFolder + "/" + toPackagePath(modelPackage, srcBasePath)); } @Override @@ -225,6 +230,39 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege return toModelName(name); } + public String toPackagePath(String packageName, String basePath) { + packageName = packageName.replace(invokerPackage, ""); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. + if (basePath != null && basePath.length() > 0) { + basePath = basePath.replaceAll("[\\\\/]?$", "") + File.separatorChar; // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. + } + + String regFirstPathSeparator; + if ("/".equals(File.separator)) { // for mac, linux + regFirstPathSeparator = "^/"; + } else { // for windows + regFirstPathSeparator = "^\\\\"; + } + + String regLastPathSeparator; + if ("/".equals(File.separator)) { // for mac, linux + regLastPathSeparator = "/$"; + } else { // for windows + regLastPathSeparator = "\\\\$"; + } + + return (getPackagePath() + File.separatorChar + basePath + // Replace period, backslash, forward slash with file separator in package name + + packageName.replaceAll("[\\.\\\\/]", Matcher.quoteReplacement(File.separator)) + // Trim prefix file separators from package path + .replaceAll(regFirstPathSeparator, "")) + // Trim trailing file separators from the overall path + .replaceAll(regLastPathSeparator+ "$", ""); + } + + public String getPackagePath() { + return packagePath; + } + @Override public String escapeQuotationMark(String input) { // remove ' to avoid code injection diff --git a/samples/server/petstore-security-test/slim/SwaggerServer/.htaccess b/samples/server/petstore-security-test/slim/.htaccess similarity index 100% rename from samples/server/petstore-security-test/slim/SwaggerServer/.htaccess rename to samples/server/petstore-security-test/slim/.htaccess diff --git a/samples/server/petstore-security-test/slim/SwaggerServer/README.md b/samples/server/petstore-security-test/slim/README.md similarity index 100% rename from samples/server/petstore-security-test/slim/SwaggerServer/README.md rename to samples/server/petstore-security-test/slim/README.md diff --git a/samples/server/petstore-security-test/slim/SwaggerServer/composer.json b/samples/server/petstore-security-test/slim/composer.json similarity index 100% rename from samples/server/petstore-security-test/slim/SwaggerServer/composer.json rename to samples/server/petstore-security-test/slim/composer.json diff --git a/samples/server/petstore-security-test/slim/composer.lock b/samples/server/petstore-security-test/slim/composer.lock new file mode 100644 index 000000000000..3007790bbebd --- /dev/null +++ b/samples/server/petstore-security-test/slim/composer.lock @@ -0,0 +1,254 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "834a8ce57aaea28f119aedff36481779", + "content-hash": "913417690829da41975a473b88f30f64", + "packages": [ + { + "name": "container-interop/container-interop", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/container-interop/container-interop.git", + "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/container-interop/container-interop/zipball/fc08354828f8fd3245f77a66b9e23a6bca48297e", + "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Interop\\Container\\": "src/Interop/Container/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", + "time": "2014-12-30 15:22:37" + }, + { + "name": "nikic/fast-route", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/nikic/FastRoute.git", + "reference": "8ea928195fa9b907f0d6e48312d323c1a13cc2af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/FastRoute/zipball/8ea928195fa9b907f0d6e48312d323c1a13cc2af", + "reference": "8ea928195fa9b907f0d6e48312d323c1a13cc2af", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "FastRoute\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "description": "Fast request router for PHP", + "keywords": [ + "router", + "routing" + ], + "time": "2016-06-12 19:08:51" + }, + { + "name": "pimple/pimple", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/silexphp/Pimple.git", + "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a30f7d6e57565a2e1a316e1baf2a483f788b258a", + "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Pimple": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Pimple, a simple Dependency Injection Container", + "homepage": "http://pimple.sensiolabs.org", + "keywords": [ + "container", + "dependency injection" + ], + "time": "2015-09-11 15:10:35" + }, + { + "name": "psr/http-message", + "version": "1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2015-05-04 20:22:00" + }, + { + "name": "slim/slim", + "version": "3.4.2", + "source": { + "type": "git", + "url": "https://github.com/slimphp/Slim.git", + "reference": "a132385f736063d00632b52b3f8a389fe66fe4fa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slimphp/Slim/zipball/a132385f736063d00632b52b3f8a389fe66fe4fa", + "reference": "a132385f736063d00632b52b3f8a389fe66fe4fa", + "shasum": "" + }, + "require": { + "container-interop/container-interop": "^1.1", + "nikic/fast-route": "^1.0", + "php": ">=5.5.0", + "pimple/pimple": "^3.0", + "psr/http-message": "^1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0", + "squizlabs/php_codesniffer": "^2.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Slim\\": "Slim" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rob Allen", + "email": "rob@akrabat.com", + "homepage": "http://akrabat.com" + }, + { + "name": "Josh Lockhart", + "email": "hello@joshlockhart.com", + "homepage": "https://joshlockhart.com" + }, + { + "name": "Gabriel Manricks", + "email": "gmanricks@me.com", + "homepage": "http://gabrielmanricks.com" + }, + { + "name": "Andrew Smith", + "email": "a.smith@silentworks.co.uk", + "homepage": "http://silentworks.co.uk" + } + ], + "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", + "homepage": "http://slimframework.com", + "keywords": [ + "api", + "framework", + "micro", + "router" + ], + "time": "2016-05-25 11:23:38" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "RC", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/samples/server/petstore-security-test/slim/SwaggerServer/index.php b/samples/server/petstore-security-test/slim/index.php similarity index 100% rename from samples/server/petstore-security-test/slim/SwaggerServer/index.php rename to samples/server/petstore-security-test/slim/index.php diff --git "a/samples/server/petstore-security-test/slim/SwaggerServer\\lib\\Models/Return.php" b/samples/server/petstore-security-test/slim/lib/Models/Return.php similarity index 80% rename from "samples/server/petstore-security-test/slim/SwaggerServer\\lib\\Models/Return.php" rename to samples/server/petstore-security-test/slim/lib/Models/Return.php index 5486ab83bf09..840ec63b561f 100644 --- "a/samples/server/petstore-security-test/slim/SwaggerServer\\lib\\Models/Return.php" +++ b/samples/server/petstore-security-test/slim/lib/Models/Return.php @@ -2,7 +2,7 @@ /* * Return */ -namespace SwaggerServer\lib\Models; +namespace \Models; /* * Return diff --git a/samples/server/petstore-security-test/slim/vendor/autoload.php b/samples/server/petstore-security-test/slim/vendor/autoload.php new file mode 100644 index 000000000000..3b476eabc3ff --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/autoload.php @@ -0,0 +1,7 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see http://www.php-fig.org/psr/psr-0/ + * @see http://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + + private $classMapAuthoritative = false; + + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + return array(); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 + if ('\\' == $class[0]) { + $class = substr($class, 1); + } + + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative) { + return false; + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if ($file === null && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if ($file === null) { + // Remember that this class does not exist. + return $this->classMap[$class] = false; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { + if (0 === strpos($class, $prefix)) { + foreach ($this->prefixDirsPsr4[$prefix] as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/samples/server/petstore-security-test/slim/vendor/composer/LICENSE b/samples/server/petstore-security-test/slim/vendor/composer/LICENSE new file mode 100644 index 000000000000..1a28124886db --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) 2016 Nils Adermann, Jordi Boggiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/samples/server/petstore-security-test/slim/vendor/composer/autoload_classmap.php b/samples/server/petstore-security-test/slim/vendor/composer/autoload_classmap.php new file mode 100644 index 000000000000..7a91153b0d8e --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/composer/autoload_classmap.php @@ -0,0 +1,9 @@ + $vendorDir . '/nikic/fast-route/src/functions.php', +); diff --git a/samples/server/petstore-security-test/slim/vendor/composer/autoload_namespaces.php b/samples/server/petstore-security-test/slim/vendor/composer/autoload_namespaces.php new file mode 100644 index 000000000000..c3cd02297dec --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/composer/autoload_namespaces.php @@ -0,0 +1,10 @@ + array($vendorDir . '/pimple/pimple/src'), +); diff --git a/samples/server/petstore-security-test/slim/vendor/composer/autoload_psr4.php b/samples/server/petstore-security-test/slim/vendor/composer/autoload_psr4.php new file mode 100644 index 000000000000..7e403d2e2d0f --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/composer/autoload_psr4.php @@ -0,0 +1,13 @@ + array($vendorDir . '/slim/slim/Slim'), + 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'), + 'Interop\\Container\\' => array($vendorDir . '/container-interop/container-interop/src/Interop/Container'), + 'FastRoute\\' => array($vendorDir . '/nikic/fast-route/src'), +); diff --git a/samples/server/petstore-security-test/slim/vendor/composer/autoload_real.php b/samples/server/petstore-security-test/slim/vendor/composer/autoload_real.php new file mode 100644 index 000000000000..cb6d95c7fcf0 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/composer/autoload_real.php @@ -0,0 +1,59 @@ + $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + + $loader->register(true); + + $includeFiles = require __DIR__ . '/autoload_files.php'; + foreach ($includeFiles as $fileIdentifier => $file) { + composerRequirea7ca9e6d69dc1fe934d8e0e81434a295($fileIdentifier, $file); + } + + return $loader; + } +} + +function composerRequirea7ca9e6d69dc1fe934d8e0e81434a295($fileIdentifier, $file) +{ + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + require $file; + + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/composer/installed.json b/samples/server/petstore-security-test/slim/vendor/composer/installed.json new file mode 100644 index 000000000000..9e041100fe23 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/composer/installed.json @@ -0,0 +1,247 @@ +[ + { + "name": "container-interop/container-interop", + "version": "1.1.0", + "version_normalized": "1.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/container-interop/container-interop.git", + "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/container-interop/container-interop/zipball/fc08354828f8fd3245f77a66b9e23a6bca48297e", + "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e", + "shasum": "" + }, + "time": "2014-12-30 15:22:37", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Interop\\Container\\": "src/Interop/Container/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Promoting the interoperability of container objects (DIC, SL, etc.)" + }, + { + "name": "nikic/fast-route", + "version": "v1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/FastRoute.git", + "reference": "8ea928195fa9b907f0d6e48312d323c1a13cc2af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/FastRoute/zipball/8ea928195fa9b907f0d6e48312d323c1a13cc2af", + "reference": "8ea928195fa9b907f0d6e48312d323c1a13cc2af", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "time": "2016-06-12 19:08:51", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "FastRoute\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "description": "Fast request router for PHP", + "keywords": [ + "router", + "routing" + ] + }, + { + "name": "psr/http-message", + "version": "1.0", + "version_normalized": "1.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2015-05-04 20:22:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ] + }, + { + "name": "pimple/pimple", + "version": "v3.0.2", + "version_normalized": "3.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/silexphp/Pimple.git", + "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a30f7d6e57565a2e1a316e1baf2a483f788b258a", + "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2015-09-11 15:10:35", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Pimple": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Pimple, a simple Dependency Injection Container", + "homepage": "http://pimple.sensiolabs.org", + "keywords": [ + "container", + "dependency injection" + ] + }, + { + "name": "slim/slim", + "version": "3.4.2", + "version_normalized": "3.4.2.0", + "source": { + "type": "git", + "url": "https://github.com/slimphp/Slim.git", + "reference": "a132385f736063d00632b52b3f8a389fe66fe4fa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slimphp/Slim/zipball/a132385f736063d00632b52b3f8a389fe66fe4fa", + "reference": "a132385f736063d00632b52b3f8a389fe66fe4fa", + "shasum": "" + }, + "require": { + "container-interop/container-interop": "^1.1", + "nikic/fast-route": "^1.0", + "php": ">=5.5.0", + "pimple/pimple": "^3.0", + "psr/http-message": "^1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0", + "squizlabs/php_codesniffer": "^2.5" + }, + "time": "2016-05-25 11:23:38", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Slim\\": "Slim" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rob Allen", + "email": "rob@akrabat.com", + "homepage": "http://akrabat.com" + }, + { + "name": "Josh Lockhart", + "email": "hello@joshlockhart.com", + "homepage": "https://joshlockhart.com" + }, + { + "name": "Gabriel Manricks", + "email": "gmanricks@me.com", + "homepage": "http://gabrielmanricks.com" + }, + { + "name": "Andrew Smith", + "email": "a.smith@silentworks.co.uk", + "homepage": "http://silentworks.co.uk" + } + ], + "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", + "homepage": "http://slimframework.com", + "keywords": [ + "api", + "framework", + "micro", + "router" + ] + } +] diff --git a/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/.gitignore b/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/.gitignore new file mode 100644 index 000000000000..b2395aa05541 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/.gitignore @@ -0,0 +1,3 @@ +composer.lock +composer.phar +/vendor/ diff --git a/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/LICENSE b/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/LICENSE new file mode 100644 index 000000000000..7671d9020f64 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 container-interop + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/README.md b/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/README.md new file mode 100644 index 000000000000..ec434d0f2683 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/README.md @@ -0,0 +1,85 @@ +# Container Interoperability + +[![Latest Stable Version](https://poser.pugx.org/container-interop/container-interop/v/stable.png)](https://packagist.org/packages/container-interop/container-interop) + +*container-interop* tries to identify and standardize features in *container* objects (service locators, +dependency injection containers, etc.) to achieve interopererability. + +Through discussions and trials, we try to create a standard, made of common interfaces but also recommendations. + +If PHP projects that provide container implementations begin to adopt these common standards, then PHP +applications and projects that use containers can depend on the common interfaces instead of specific +implementations. This facilitates a high-level of interoperability and flexibility that allows users to consume +*any* container implementation that can be adapted to these interfaces. + +The work done in this project is not officially endorsed by the [PHP-FIG](http://www.php-fig.org/), but it is being +worked on by members of PHP-FIG and other good developers. We adhere to the spirit and ideals of PHP-FIG, and hope +this project will pave the way for one or more future PSRs. + + +## Installation + +You can install this package through Composer: + +```json +{ + "require": { + "container-interop/container-interop": "~1.0" + } +} +``` + +The packages adheres to the [SemVer](http://semver.org/) specification, and there will be full backward compatibility +between minor versions. + +## Standards + +### Available + +- [`ContainerInterface`](src/Interop/Container/ContainerInterface.php). +[Description](docs/ContainerInterface.md) [Meta Document](docs/ContainerInterface-meta.md). +Describes the interface of a container that exposes methods to read its entries. +- [*Delegate lookup feature*](docs/Delegate-lookup.md). +[Meta Document](docs/Delegate-lookup-meta.md). +Describes the ability for a container to delegate the lookup of its dependencies to a third-party container. This +feature lets several containers work together in a single application. + +### Proposed + +View open [request for comments](https://github.com/container-interop/container-interop/labels/RFC) + +## Compatible projects + +### Projects implementing `ContainerInterface` + +- [Acclimate](https://github.com/jeremeamia/acclimate-container) +- [dcp-di](https://github.com/estelsmith/dcp-di) +- [Mouf](http://mouf-php.com) +- [Njasm Container](https://github.com/njasm/container) +- [PHP-DI](http://php-di.org) +- [PimpleInterop](https://github.com/moufmouf/pimple-interop) +- [XStatic](https://github.com/jeremeamia/xstatic) + +### Projects implementing the *delegate lookup* feature + +- [Mouf](http://mouf-php.com) +- [PHP-DI](http://php-di.org) +- [PimpleInterop](https://github.com/moufmouf/pimple-interop) + +## Workflow + +Everyone is welcome to join and contribute. + +The general workflow looks like this: + +1. Someone opens a discussion (GitHub issue) to suggest an interface +1. Feedback is gathered +1. The interface is added to a development branch +1. We release alpha versions so that the interface can be experimented with +1. Discussions and edits ensue until the interface is deemed stable by a general consensus +1. A new minor version of the package is released + +We try to not break BC by creating new interfaces instead of editing existing ones. + +While we currently work on interfaces, we are open to anything that might help towards interoperability, may that +be code, best practices, etc. diff --git a/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/composer.json b/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/composer.json new file mode 100644 index 000000000000..84f38752822f --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/composer.json @@ -0,0 +1,11 @@ +{ + "name": "container-interop/container-interop", + "type": "library", + "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", + "license": "MIT", + "autoload": { + "psr-4": { + "Interop\\Container\\": "src/Interop/Container/" + } + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/ContainerInterface-meta.md b/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/ContainerInterface-meta.md new file mode 100644 index 000000000000..90711c9051d2 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/ContainerInterface-meta.md @@ -0,0 +1,114 @@ +# ContainerInterface Meta Document + +## Introduction + +This document describes the process and discussions that lead to the `ContainerInterface`. +Its goal is to explain the reasons behind each decision. + +## Goal + +The goal set by `ContainerInterface` is to standardize how frameworks and libraries make use of a +container to obtain objects and parameters. + +By standardizing such a behavior, frameworks and libraries using the `ContainerInterface` +could work with any compatible container. +That would allow end users to choose their own container based on their own preferences. + +It is important to distinguish the two usages of a container: + +- configuring entries +- fetching entries + +Most of the time, those two sides are not used by the same party. +While it is often end users who tend to configure entries, it is generally the framework that fetch +entries to build the application. + +This is why this interface focuses only on how entries can be fetched from a container. + +## Interface name + +The interface name has been thoroughly discussed and was decided by a vote. + +The list of options considered with their respective votes are: + +- `ContainerInterface`: +8 +- `ProviderInterface`: +2 +- `LocatorInterface`: 0 +- `ReadableContainerInterface`: -5 +- `ServiceLocatorInterface`: -6 +- `ObjectFactory`: -6 +- `ObjectStore`: -8 +- `ConsumerInterface`: -9 + +[Full results of the vote](https://github.com/container-interop/container-interop/wiki/%231-interface-name:-Vote) + +The complete discussion can be read in [the issue #1](https://github.com/container-interop/container-interop/issues/1). + +## Interface methods + +The choice of which methods the interface would contain was made after a statistical analysis of existing containers. +The results of this analysis are available [in this document](https://gist.github.com/mnapoli/6159681). + +The summary of the analysis showed that: + +- all containers offer a method to get an entry by its id +- a large majority name such method `get()` +- for all containers, the `get()` method has 1 mandatory parameter of type string +- some containers have an optional additional argument for `get()`, but it doesn't same the same purpose between containers +- a large majority of the containers offer a method to test if it can return an entry by its id +- a majority name such method `has()` +- for all containers offering `has()`, the method has exactly 1 parameter of type string +- a large majority of the containers throw an exception rather than returning null when an entry is not found in `get()` +- a large majority of the containers don't implement `ArrayAccess` + +The question of whether to include methods to define entries has been discussed in +[issue #1](https://github.com/container-interop/container-interop/issues/1). +It has been judged that such methods do not belong in the interface described here because it is out of its scope +(see the "Goal" section). + +As a result, the `ContainerInterface` contains two methods: + +- `get()`, returning anything, with one mandatory string parameter. Should throw an exception if the entry is not found. +- `has()`, returning a boolean, with one mandatory string parameter. + +### Number of parameters in `get()` method + +While `ContainerInterface` only defines one mandatory parameter in `get()`, it is not incompatible with +existing containers that have additional optional parameters. PHP allows an implementation to offer more parameters +as long as they are optional, because the implementation *does* satisfy the interface. + +This issue has been discussed in [issue #6](https://github.com/container-interop/container-interop/issues/6). + +### Type of the `$id` parameter + +The type of the `$id` parameter in `get()` and `has()` has been discussed in +[issue #6](https://github.com/container-interop/container-interop/issues/6). +While `string` is used in all the containers that were analyzed, it was suggested that allowing +anything (such as objects) could allow containers to offer a more advanced query API. + +An example given was to use the container as an object builder. The `$id` parameter would then be an +object that would describe how to create an instance. + +The conclusion of the discussion was that this was beyond the scope of getting entries from a container without +knowing how the container provided them, and it was more fit for a factory. + +## Contributors + +Are listed here all people that contributed in the discussions or votes, by alphabetical order: + +- [Amy Stephen](https://github.com/AmyStephen) +- [David Négrier](https://github.com/moufmouf) +- [Don Gilbert](https://github.com/dongilbert) +- [Jason Judge](https://github.com/judgej) +- [Jeremy Lindblom](https://github.com/jeremeamia) +- [Marco Pivetta](https://github.com/Ocramius) +- [Matthieu Napoli](https://github.com/mnapoli) +- [Paul M. Jones](https://github.com/pmjones) +- [Stephan Hochdörfer](https://github.com/shochdoerfer) +- [Taylor Otwell](https://github.com/taylorotwell) + +## Relevant links + +- [`ContainerInterface.php`](https://github.com/container-interop/container-interop/blob/master/src/Interop/Container/ContainerInterface.php) +- [List of all issues](https://github.com/container-interop/container-interop/issues?labels=ContainerInterface&milestone=&page=1&state=closed) +- [Vote for the interface name](https://github.com/container-interop/container-interop/wiki/%231-interface-name:-Vote) diff --git a/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/ContainerInterface.md b/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/ContainerInterface.md new file mode 100644 index 000000000000..9f609674c801 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/ContainerInterface.md @@ -0,0 +1,153 @@ +Container interface +=================== + +This document describes a common interface for dependency injection containers. + +The goal set by `ContainerInterface` is to standardize how frameworks and libraries make use of a +container to obtain objects and parameters (called *entries* in the rest of this document). + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", +"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be +interpreted as described in [RFC 2119][]. + +The word `implementor` in this document is to be interpreted as someone +implementing the `ContainerInterface` in a depency injection-related library or framework. +Users of dependency injections containers (DIC) are refered to as `user`. + +[RFC 2119]: http://tools.ietf.org/html/rfc2119 + +1. Specification +----------------- + +### 1.1 Basics + +- The `Interop\Container\ContainerInterface` exposes two methods : `get` and `has`. + +- `get` takes one mandatory parameter: an entry identifier. It MUST be a string. + A call to `get` can return anything (a *mixed* value), or throws an exception if the identifier + is not known to the container. Two successive calls to `get` with the same + identifier SHOULD return the same value. However, depending on the `implementor` + design and/or `user` configuration, different values might be returned, so + `user` SHOULD NOT rely on getting the same value on 2 successive calls. + While `ContainerInterface` only defines one mandatory parameter in `get()`, implementations + MAY accept additional optional parameters. + +- `has` takes one unique parameter: an entry identifier. It MUST return `true` + if an entry identifier is known to the container and `false` if it is not. + +### 1.2 Exceptions + +Exceptions directly thrown by the container MUST implement the +[`Interop\Container\Exception\ContainerException`](../src/Interop/Container/Exception/ContainerException.php). + +A call to the `get` method with a non-existing id should throw a +[`Interop\Container\Exception\NotFoundException`](../src/Interop/Container/Exception/NotFoundException.php). + +### 1.3 Additional features + +This section describes additional features that MAY be added to a container. Containers are not +required to implement these features to respect the ContainerInterface. + +#### 1.3.1 Delegate lookup feature + +The goal of the *delegate lookup* feature is to allow several containers to share entries. +Containers implementing this feature can perform dependency lookups in other containers. + +Containers implementing this feature will offer a greater lever of interoperability +with other containers. Implementation of this feature is therefore RECOMMENDED. + +A container implementing this feature: + +- MUST implement the `ContainerInterface` +- MUST provide a way to register a delegate container (using a constructor parameter, or a setter, + or any possible way). The delegate container MUST implement the `ContainerInterface`. + +When a container is configured to use a delegate container for dependencies: + +- Calls to the `get` method should only return an entry if the entry is part of the container. + If the entry is not part of the container, an exception should be thrown + (as requested by the `ContainerInterface`). +- Calls to the `has` method should only return `true` if the entry is part of the container. + If the entry is not part of the container, `false` should be returned. +- If the fetched entry has dependencies, **instead** of performing + the dependency lookup in the container, the lookup is performed on the *delegate container*. + +Important! By default, the lookup SHOULD be performed on the delegate container **only**, not on the container itself. + +It is however allowed for containers to provide exception cases for special entries, and a way to lookup +into the same container (or another container) instead of the delegate container. + +2. Package +---------- + +The interfaces and classes described as well as relevant exception are provided as part of the +[container-interop/container-interop](https://packagist.org/packages/container-interop/container-interop) package. + +3. `Interop\Container\ContainerInterface` +----------------------------------------- + +```php +setParentContainer($this); + } + } + ... + } +} + +``` + +**Cons:** + +Cons have been extensively discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51721777). +Basically, forcing a setter into an interface is a bad idea. Setters are similar to constructor arguments, +and it's a bad idea to standardize a constructor: how the delegate container is configured into a container is an implementation detail. This outweights the benefits of the interface. + +### 4.4 Alternative: no exception case for delegate lookups + +Originally, the proposed wording for delegate lookup calls was: + +> Important! The lookup MUST be performed on the delegate container **only**, not on the container itself. + +This was later replaced by: + +> Important! By default, the lookup SHOULD be performed on the delegate container **only**, not on the container itself. +> +> It is however allowed for containers to provide exception cases for special entries, and a way to lookup +> into the same container (or another container) instead of the delegate container. + +Exception cases have been allowed to avoid breaking dependencies with some services that must be provided +by the container (on @njasm proposal). This was proposed here: https://github.com/container-interop/container-interop/pull/20#issuecomment-56597235 + +### 4.5 Alternative: having one of the containers act as the composite container + +In real-life scenarios, we usually have a big framework (Symfony 2, Zend Framework 2, etc...) and we want to +add another DI container to this container. Most of the time, the "big" framework will be responsible for +creating the controller's instances, using it's own DI container. Until *container-interop* is fully adopted, +the "big" framework will not be aware of the existence of a composite container that it should use instead +of its own container. + +For this real-life use cases, @mnapoli and @moufmouf proposed to extend the "big" framework's DI container +to make it act as a composite container. + +This has been discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-40367194) +and [here](http://mouf-php.com/container-interop-whats-next#solution4). + +This was implemented in Symfony 2 using: + +- [interop.symfony.di](https://github.com/thecodingmachine/interop.symfony.di/tree/v0.1.0) +- [framework interop](https://github.com/mnapoli/framework-interop/) + +This was implemented in Silex using: + +- [interop.silex.di](https://github.com/thecodingmachine/interop.silex.di) + +Having a container act as the composite container is not part of the delegate lookup standard because it is +simply a temporary design pattern used to make existing frameworks that do not support yet ContainerInterop +play nice with other DI containers. + + +5. Implementations +------------------ + +The following projects already implement the delegate lookup feature: + +- [Mouf](http://mouf-php.com), through the [`setDelegateLookupContainer` method](https://github.com/thecodingmachine/mouf/blob/2.0/src/Mouf/MoufManager.php#L2120) +- [PHP-DI](http://php-di.org/), through the [`$wrapperContainer` parameter of the constructor](https://github.com/mnapoli/PHP-DI/blob/master/src/DI/Container.php#L72) +- [pimple-interop](https://github.com/moufmouf/pimple-interop), through the [`$container` parameter of the constructor](https://github.com/moufmouf/pimple-interop/blob/master/src/Interop/Container/Pimple/PimpleInterop.php#L62) + +6. People +--------- + +Are listed here all people that contributed in the discussions, by alphabetical order: + +- [Alexandru Pătrănescu](https://github.com/drealecs) +- [Ben Peachey](https://github.com/potherca) +- [David Négrier](https://github.com/moufmouf) +- [Jeremy Lindblom](https://github.com/jeremeamia) +- [Marco Pivetta](https://github.com/Ocramius) +- [Matthieu Napoli](https://github.com/mnapoli) +- [Nelson J Morais](https://github.com/njasm) +- [Phil Sturgeon](https://github.com/philsturgeon) +- [Stephan Hochdörfer](https://github.com/shochdoerfer) + +7. Relevant Links +----------------- + +_**Note:** Order descending chronologically._ + +- [Pull request on the delegate lookup feature](https://github.com/container-interop/container-interop/pull/20) +- [Pull request on the interface idea](https://github.com/container-interop/container-interop/pull/8) +- [Original article exposing the delegate lookup idea along many others](http://mouf-php.com/container-interop-whats-next) + diff --git a/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/Delegate-lookup.md b/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/Delegate-lookup.md new file mode 100644 index 000000000000..04eb3aea023d --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/Delegate-lookup.md @@ -0,0 +1,60 @@ +Delegate lookup feature +======================= + +This document describes a standard for dependency injection containers. + +The goal set by the *delegate lookup* feature is to allow several containers to share entries. +Containers implementing this feature can perform dependency lookups in other containers. + +Containers implementing this feature will offer a greater lever of interoperability +with other containers. Implementation of this feature is therefore RECOMMENDED. + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", +"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be +interpreted as described in [RFC 2119][]. + +The word `implementor` in this document is to be interpreted as someone +implementing the delegate lookup feature in a dependency injection-related library or framework. +Users of dependency injections containers (DIC) are refered to as `user`. + +[RFC 2119]: http://tools.ietf.org/html/rfc2119 + +1. Vocabulary +------------- + +In a dependency injection container, the container is used to fetch entries. +Entries can have dependencies on other entries. Usually, these other entries are fetched by the container. + +The *delegate lookup* feature is the ability for a container to fetch dependencies in +another container. In the rest of the document, the word "container" will reference the container +implemented by the implementor. The word "delegate container" will reference the container we are +fetching the dependencies from. + +2. Specification +---------------- + +A container implementing the *delegate lookup* feature: + +- MUST implement the [`ContainerInterface`](ContainerInterface.md) +- MUST provide a way to register a delegate container (using a constructor parameter, or a setter, + or any possible way). The delegate container MUST implement the [`ContainerInterface`](ContainerInterface.md). + +When a container is configured to use a delegate container for dependencies: + +- Calls to the `get` method should only return an entry if the entry is part of the container. + If the entry is not part of the container, an exception should be thrown + (as requested by the [`ContainerInterface`](ContainerInterface.md)). +- Calls to the `has` method should only return `true` if the entry is part of the container. + If the entry is not part of the container, `false` should be returned. +- If the fetched entry has dependencies, **instead** of performing + the dependency lookup in the container, the lookup is performed on the *delegate container*. + +Important: By default, the dependency lookups SHOULD be performed on the delegate container **only**, not on the container itself. + +It is however allowed for containers to provide exception cases for special entries, and a way to lookup +into the same container (or another container) instead of the delegate container. + +3. Package / Interface +---------------------- + +This feature is not tied to any code, interface or package. diff --git a/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/images/interoperating_containers.png b/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/images/interoperating_containers.png new file mode 100644 index 0000000000000000000000000000000000000000..9c672e16c72a08708ea5bdeb51757c2951d3ee66 GIT binary patch literal 35971 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 literal 0 HcmV?d00001 diff --git a/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/images/priority.png b/samples/server/petstore-security-test/slim/vendor/container-interop/container-interop/docs/images/priority.png new file mode 100644 index 0000000000000000000000000000000000000000..5760dc71b557fea7ec5bd5699adfd1c228b9cdec GIT binary patch literal 22949 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 + } + + class RouteCollector { + public function __construct(RouteParser $routeParser, DataGenerator $dataGenerator); + public function addRoute(mixed $httpMethod, string $route, mixed $handler): void; + public function getData(): array; + } + + class Route { + public function __construct(string $httpMethod, mixed $handler, string $regex, array $variables); + public function matches(string $str): bool; + } + + interface DataGenerator { + public function addRoute(string $httpMethod, array $routeData, mixed $handler); + public function getData(): array; + } + + interface Dispatcher { + const int NOT_FOUND = 0; + const int FOUND = 1; + const int METHOD_NOT_ALLOWED = 2; + public function dispatch(string $httpMethod, string $uri): array; + } + + function simpleDispatcher( + (function(RouteCollector): void) $routeDefinitionCallback, + shape( + 'routeParser' => ?classname, + 'dataGenerator' => ?classname, + 'dispatcher' => ?classname, + 'routeCollector' => ?classname, + ) $options = shape()): Dispatcher; + + function cachedDispatcher( + (function(RouteCollector): void) $routeDefinitionCallback, + shape( + 'routeParser' => ?classname, + 'dataGenerator' => ?classname, + 'dispatcher' => ?classname, + 'routeCollector' => ?classname, + 'cacheDisabled' => ?bool, + 'cacheFile' => ?string, + ) $options = shape()): Dispatcher; +} + +namespace FastRoute\DataGenerator { + abstract class RegexBasedAbstract implements \FastRoute\DataGenerator { + protected abstract function getApproxChunkSize(); + protected abstract function processChunk($regexToRoutesMap); + + public function addRoute(string $httpMethod, array $routeData, mixed $handler): void; + public function getData(): array; + } + + class CharCountBased extends RegexBasedAbstract { + protected function getApproxChunkSize(): int; + protected function processChunk(array $regexToRoutesMap): array; + } + + class GroupCountBased extends RegexBasedAbstract { + protected function getApproxChunkSize(): int; + protected function processChunk(array $regexToRoutesMap): array; + } + + class GroupPosBased extends RegexBasedAbstract { + protected function getApproxChunkSize(): int; + protected function processChunk(array $regexToRoutesMap): array; + } + + class MarkBased extends RegexBasedAbstract { + protected function getApproxChunkSize(): int; + protected function processChunk(array $regexToRoutesMap): array; + } +} + +namespace FastRoute\Dispatcher { + abstract class RegexBasedAbstract implements \FastRoute\Dispatcher { + protected abstract function dispatchVariableRoute(array $routeData, string $uri): array; + + public function dispatch(string $httpMethod, string $uri): array; + } + + class GroupPosBased extends RegexBasedAbstract { + public function __construct(array $data); + protected function dispatchVariableRoute(array $routeData, string $uri): array; + } + + class GroupCountBased extends RegexBasedAbstract { + public function __construct(array $data); + protected function dispatchVariableRoute(array $routeData, string $uri): array; + } + + class CharCountBased extends RegexBasedAbstract { + public function __construct(array $data); + protected function dispatchVariableRoute(array $routeData, string $uri): array; + } + + class MarkBased extends RegexBasedAbstract { + public function __construct(array $data); + protected function dispatchVariableRoute(array $routeData, string $uri): array; + } +} + +namespace FastRoute\RouteParser { + class Std implements \FastRoute\RouteParser { + const string VARIABLE_REGEX = <<<'REGEX' +\{ + \s* ([a-zA-Z][a-zA-Z0-9_]*) \s* + (?: + : \s* ([^{}]*(?:\{(?-1)\}[^{}]*)*) + )? +\} +REGEX; + const string DEFAULT_DISPATCH_REGEX = '[^/]+'; + public function parse(string $route): array; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/LICENSE b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/LICENSE new file mode 100644 index 000000000000..478e7641e93d --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/LICENSE @@ -0,0 +1,31 @@ +Copyright (c) 2013 by Nikita Popov. + +Some rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/README.md b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/README.md new file mode 100644 index 000000000000..f812a2a014ca --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/README.md @@ -0,0 +1,273 @@ +FastRoute - Fast request router for PHP +======================================= + +This library provides a fast implementation of a regular expression based router. [Blog post explaining how the +implementation works and why it is fast.][blog_post] + +Install +------- + +To install with composer: + +```sh +composer require nikic/fast-route +``` + +Requires PHP 5.4 or newer. + +Usage +----- + +Here's a basic usage example: + +```php +addRoute('GET', '/users', 'get_all_users_handler'); + // {id} must be a number (\d+) + $r->addRoute('GET', '/user/{id:\d+}', 'get_user_handler'); + // The /{title} suffix is optional + $r->addRoute('GET', '/articles/{id:\d+}[/{title}]', 'get_article_handler'); +}); + +// Fetch method and URI from somewhere +$httpMethod = $_SERVER['REQUEST_METHOD']; +$uri = $_SERVER['REQUEST_URI']; + +// Strip query string (?foo=bar) and decode URI +if (false !== $pos = strpos($uri, '?')) { + $uri = substr($uri, 0, $pos); +} +$uri = rawurldecode($uri); + +$routeInfo = $dispatcher->dispatch($httpMethod, $uri); +switch ($routeInfo[0]) { + case FastRoute\Dispatcher::NOT_FOUND: + // ... 404 Not Found + break; + case FastRoute\Dispatcher::METHOD_NOT_ALLOWED: + $allowedMethods = $routeInfo[1]; + // ... 405 Method Not Allowed + break; + case FastRoute\Dispatcher::FOUND: + $handler = $routeInfo[1]; + $vars = $routeInfo[2]; + // ... call $handler with $vars + break; +} +``` + +### Defining routes + +The routes are defined by calling the `FastRoute\simpleDispatcher()` function, which accepts +a callable taking a `FastRoute\RouteCollector` instance. The routes are added by calling +`addRoute()` on the collector instance: + +```php +$r->addRoute($method, $routePattern, $handler); +``` + +The `$method` is an uppercase HTTP method string for which a certain route should match. It +is possible to specify multiple valid methods using an array: + +```php +// These two calls +$r->addRoute('GET', '/test', 'handler'); +$r->addRoute('POST', '/test', 'handler'); +// Are equivalent to this one call +$r->addRoute(['GET', 'POST'], '/test', 'handler'); +``` + +By default the `$routePattern` uses a syntax where `{foo}` specifies a placeholder with name `foo` +and matching the regex `[^/]+`. To adjust the pattern the placeholder matches, you can specify +a custom pattern by writing `{bar:[0-9]+}`. Some examples: + +```php +// Matches /user/42, but not /user/xyz +$r->addRoute('GET', '/user/{id:\d+}', 'handler'); + +// Matches /user/foobar, but not /user/foo/bar +$r->addRoute('GET', '/user/{name}', 'handler'); + +// Matches /user/foo/bar as well +$r->addRoute('GET', '/user/{name:.+}', 'handler'); +``` + +Custom patterns for route placeholders cannot use capturing groups. For example `{lang:(en|de)}` +is not a valid placeholder, because `()` is a capturing group. Instead you can use either +`{lang:en|de}` or `{lang:(?:en|de)}`. + +Furthermore parts of the route enclosed in `[...]` are considered optional, so that `/foo[bar]` +will match both `/foo` and `/foobar`. Optional parts are only supported in a trailing position, +not in the middle of a route. + +```php +// This route +$r->addRoute('GET', '/user/{id:\d+}[/{name}]', 'handler'); +// Is equivalent to these two routes +$r->addRoute('GET', '/user/{id:\d+}', 'handler'); +$r->addRoute('GET', '/user/{id:\d+}/{name}', 'handler'); + +// Multiple nested optional parts are possible as well +$r->addRoute('GET', '/user[/{id:\d+}[/{name}]]', 'handler'); + +// This route is NOT valid, because optional parts can only occur at the end +$r->addRoute('GET', '/user[/{id:\d+}]/{name}', 'handler'); +``` + +The `$handler` parameter does not necessarily have to be a callback, it could also be a controller +class name or any other kind of data you wish to associate with the route. FastRoute only tells you +which handler corresponds to your URI, how you interpret it is up to you. + +### Caching + +The reason `simpleDispatcher` accepts a callback for defining the routes is to allow seamless +caching. By using `cachedDispatcher` instead of `simpleDispatcher` you can cache the generated +routing data and construct the dispatcher from the cached information: + +```php +addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0'); + $r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1'); + $r->addRoute('GET', '/user/{name}', 'handler2'); +}, [ + 'cacheFile' => __DIR__ . '/route.cache', /* required */ + 'cacheDisabled' => IS_DEBUG_ENABLED, /* optional, enabled by default */ +]); +``` + +The second parameter to the function is an options array, which can be used to specify the cache +file location, among other things. + +### Dispatching a URI + +A URI is dispatched by calling the `dispatch()` method of the created dispatcher. This method +accepts the HTTP method and a URI. Getting those two bits of information (and normalizing them +appropriately) is your job - this library is not bound to the PHP web SAPIs. + +The `dispatch()` method returns an array whose first element contains a status code. It is one +of `Dispatcher::NOT_FOUND`, `Dispatcher::METHOD_NOT_ALLOWED` and `Dispatcher::FOUND`. For the +method not allowed status the second array element contains a list of HTTP methods allowed for +the supplied URI. For example: + + [FastRoute\Dispatcher::METHOD_NOT_ALLOWED, ['GET', 'POST']] + +> **NOTE:** The HTTP specification requires that a `405 Method Not Allowed` response include the +`Allow:` header to detail available methods for the requested resource. Applications using FastRoute +should use the second array element to add this header when relaying a 405 response. + +For the found status the second array element is the handler that was associated with the route +and the third array element is a dictionary of placeholder names to their values. For example: + + /* Routing against GET /user/nikic/42 */ + + [FastRoute\Dispatcher::FOUND, 'handler0', ['name' => 'nikic', 'id' => '42']] + +### Overriding the route parser and dispatcher + +The routing process makes use of three components: A route parser, a data generator and a +dispatcher. The three components adhere to the following interfaces: + +```php + 'FastRoute\\RouteParser\\Std', + 'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased', + 'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased', +]); +``` + +The above options array corresponds to the defaults. By replacing `GroupCountBased` by +`GroupPosBased` you could switch to a different dispatching strategy. + +### A Note on HEAD Requests + +The HTTP spec requires servers to [support both GET and HEAD methods][2616-511]: + +> The methods GET and HEAD MUST be supported by all general-purpose servers + +To avoid forcing users to manually register HEAD routes for each resource we fallback to matching an +available GET route for a given resource. The PHP web SAPI transparently removes the entity body +from HEAD responses so this behavior has no effect on the vast majority of users. + +However, implementers using FastRoute outside the web SAPI environment (e.g. a custom server) MUST +NOT send entity bodies generated in response to HEAD requests. If you are a non-SAPI user this is +*your responsibility*; FastRoute has no purview to prevent you from breaking HTTP in such cases. + +Finally, note that applications MAY always specify their own HEAD method route for a given +resource to bypass this behavior entirely. + +### Credits + +This library is based on a router that [Levi Morrison][levi] implemented for the Aerys server. + +A large number of tests, as well as HTTP compliance considerations, were provided by [Daniel Lowrey][rdlowrey]. + + +[2616-511]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.1 "RFC 2616 Section 5.1.1" +[blog_post]: http://nikic.github.io/2014/02/18/Fast-request-routing-using-regular-expressions.html +[levi]: https://github.com/morrisonlevi +[rdlowrey]: https://github.com/rdlowrey diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/composer.json b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/composer.json new file mode 100644 index 000000000000..62aad22b0ce0 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/composer.json @@ -0,0 +1,21 @@ +{ + "name": "nikic/fast-route", + "description": "Fast request router for PHP", + "keywords": ["routing", "router"], + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "require": { + "php": ">=5.4.0" + }, + "autoload": { + "psr-4": { + "FastRoute\\": "src/" + }, + "files": ["src/functions.php"] + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/phpunit.xml b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/phpunit.xml new file mode 100644 index 000000000000..3c807b6acbcd --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/phpunit.xml @@ -0,0 +1,24 @@ + + + + + + ./test/ + + + + + + ./src/ + + + diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/BadRouteException.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/BadRouteException.php new file mode 100644 index 000000000000..7e38479661e0 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/BadRouteException.php @@ -0,0 +1,6 @@ + $route) { + $suffixLen++; + $suffix .= "\t"; + + $regexes[] = '(?:' . $regex . '/(\t{' . $suffixLen . '})\t{' . ($count - $suffixLen) . '})'; + $routeMap[$suffix] = [$route->handler, $route->variables]; + } + + $regex = '~^(?|' . implode('|', $regexes) . ')$~'; + return ['regex' => $regex, 'suffix' => '/' . $suffix, 'routeMap' => $routeMap]; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php new file mode 100644 index 000000000000..d51807f0772c --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php @@ -0,0 +1,28 @@ + $route) { + $numVariables = count($route->variables); + $numGroups = max($numGroups, $numVariables); + + $regexes[] = $regex . str_repeat('()', $numGroups - $numVariables); + $routeMap[$numGroups + 1] = [$route->handler, $route->variables]; + + ++$numGroups; + } + + $regex = '~^(?|' . implode('|', $regexes) . ')$~'; + return ['regex' => $regex, 'routeMap' => $routeMap]; + } +} + diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php new file mode 100644 index 000000000000..4152f7a7efc9 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php @@ -0,0 +1,25 @@ + $route) { + $regexes[] = $regex; + $routeMap[$offset] = [$route->handler, $route->variables]; + + $offset += count($route->variables); + } + + $regex = '~^(?:' . implode('|', $regexes) . ')$~'; + return ['regex' => $regex, 'routeMap' => $routeMap]; + } +} + diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/DataGenerator/MarkBased.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/DataGenerator/MarkBased.php new file mode 100644 index 000000000000..61359f5e73f6 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/DataGenerator/MarkBased.php @@ -0,0 +1,25 @@ + $route) { + $regexes[] = $regex . '(*MARK:' . $markName . ')'; + $routeMap[$markName] = [$route->handler, $route->variables]; + + ++$markName; + } + + $regex = '~^(?|' . implode('|', $regexes) . ')$~'; + return ['regex' => $regex, 'routeMap' => $routeMap]; + } +} + diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php new file mode 100644 index 000000000000..713d8972f5ae --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php @@ -0,0 +1,144 @@ +isStaticRoute($routeData)) { + $this->addStaticRoute($httpMethod, $routeData, $handler); + } else { + $this->addVariableRoute($httpMethod, $routeData, $handler); + } + } + + public function getData() { + if (empty($this->methodToRegexToRoutesMap)) { + return [$this->staticRoutes, []]; + } + + return [$this->staticRoutes, $this->generateVariableRouteData()]; + } + + private function generateVariableRouteData() { + $data = []; + foreach ($this->methodToRegexToRoutesMap as $method => $regexToRoutesMap) { + $chunkSize = $this->computeChunkSize(count($regexToRoutesMap)); + $chunks = array_chunk($regexToRoutesMap, $chunkSize, true); + $data[$method] = array_map([$this, 'processChunk'], $chunks); + } + return $data; + } + + private function computeChunkSize($count) { + $numParts = max(1, round($count / $this->getApproxChunkSize())); + return ceil($count / $numParts); + } + + private function isStaticRoute($routeData) { + return count($routeData) === 1 && is_string($routeData[0]); + } + + private function addStaticRoute($httpMethod, $routeData, $handler) { + $routeStr = $routeData[0]; + + if (isset($this->staticRoutes[$httpMethod][$routeStr])) { + throw new BadRouteException(sprintf( + 'Cannot register two routes matching "%s" for method "%s"', + $routeStr, $httpMethod + )); + } + + if (isset($this->methodToRegexToRoutesMap[$httpMethod])) { + foreach ($this->methodToRegexToRoutesMap[$httpMethod] as $route) { + if ($route->matches($routeStr)) { + throw new BadRouteException(sprintf( + 'Static route "%s" is shadowed by previously defined variable route "%s" for method "%s"', + $routeStr, $route->regex, $httpMethod + )); + } + } + } + + $this->staticRoutes[$httpMethod][$routeStr] = $handler; + } + + private function addVariableRoute($httpMethod, $routeData, $handler) { + list($regex, $variables) = $this->buildRegexForRoute($routeData); + + if (isset($this->methodToRegexToRoutesMap[$httpMethod][$regex])) { + throw new BadRouteException(sprintf( + 'Cannot register two routes matching "%s" for method "%s"', + $regex, $httpMethod + )); + } + + $this->methodToRegexToRoutesMap[$httpMethod][$regex] = new Route( + $httpMethod, $handler, $regex, $variables + ); + } + + private function buildRegexForRoute($routeData) { + $regex = ''; + $variables = []; + foreach ($routeData as $part) { + if (is_string($part)) { + $regex .= preg_quote($part, '~'); + continue; + } + + list($varName, $regexPart) = $part; + + if (isset($variables[$varName])) { + throw new BadRouteException(sprintf( + 'Cannot use the same placeholder "%s" twice', $varName + )); + } + + if ($this->regexHasCapturingGroups($regexPart)) { + throw new BadRouteException(sprintf( + 'Regex "%s" for parameter "%s" contains a capturing group', + $regexPart, $varName + )); + } + + $variables[$varName] = $varName; + $regex .= '(' . $regexPart . ')'; + } + + return [$regex, $variables]; + } + + private function regexHasCapturingGroups($regex) { + if (false === strpos($regex, '(')) { + // Needs to have at least a ( to contain a capturing group + return false; + } + + // Semi-accurate detection for capturing groups + return preg_match( + '~ + (?: + \(\?\( + | \[ [^\]\\\\]* (?: \\\\ . [^\]\\\\]* )* \] + | \\\\ . + ) (*SKIP)(*FAIL) | + \( + (?! + \? (?! <(?![!=]) | P< | \' ) + | \* + ) + ~x', + $regex + ); + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher.php new file mode 100644 index 000000000000..ea98009bd264 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher.php @@ -0,0 +1,25 @@ + 'value', ...]] + * + * @param string $httpMethod + * @param string $uri + * + * @return array + */ + public function dispatch($httpMethod, $uri); +} diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php new file mode 100644 index 000000000000..22ba2406f1e8 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php @@ -0,0 +1,28 @@ +staticRouteMap, $this->variableRouteData) = $data; + } + + protected function dispatchVariableRoute($routeData, $uri) { + foreach ($routeData as $data) { + if (!preg_match($data['regex'], $uri . $data['suffix'], $matches)) { + continue; + } + + list($handler, $varNames) = $data['routeMap'][end($matches)]; + + $vars = []; + $i = 0; + foreach ($varNames as $varName) { + $vars[$varName] = $matches[++$i]; + } + return [self::FOUND, $handler, $vars]; + } + + return [self::NOT_FOUND]; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php new file mode 100644 index 000000000000..0abd32231309 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php @@ -0,0 +1,28 @@ +staticRouteMap, $this->variableRouteData) = $data; + } + + protected function dispatchVariableRoute($routeData, $uri) { + foreach ($routeData as $data) { + if (!preg_match($data['regex'], $uri, $matches)) { + continue; + } + + list($handler, $varNames) = $data['routeMap'][count($matches)]; + + $vars = []; + $i = 0; + foreach ($varNames as $varName) { + $vars[$varName] = $matches[++$i]; + } + return [self::FOUND, $handler, $vars]; + } + + return [self::NOT_FOUND]; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php new file mode 100644 index 000000000000..32227d4944d2 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php @@ -0,0 +1,30 @@ +staticRouteMap, $this->variableRouteData) = $data; + } + + protected function dispatchVariableRoute($routeData, $uri) { + foreach ($routeData as $data) { + if (!preg_match($data['regex'], $uri, $matches)) { + continue; + } + + // find first non-empty match + for ($i = 1; '' === $matches[$i]; ++$i); + + list($handler, $varNames) = $data['routeMap'][$i]; + + $vars = []; + foreach ($varNames as $varName) { + $vars[$varName] = $matches[$i++]; + } + return [self::FOUND, $handler, $vars]; + } + + return [self::NOT_FOUND]; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/MarkBased.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/MarkBased.php new file mode 100644 index 000000000000..fefa71185711 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/MarkBased.php @@ -0,0 +1,28 @@ +staticRouteMap, $this->variableRouteData) = $data; + } + + protected function dispatchVariableRoute($routeData, $uri) { + foreach ($routeData as $data) { + if (!preg_match($data['regex'], $uri, $matches)) { + continue; + } + + list($handler, $varNames) = $data['routeMap'][$matches['MARK']]; + + $vars = []; + $i = 0; + foreach ($varNames as $varName) { + $vars[$varName] = $matches[++$i]; + } + return [self::FOUND, $handler, $vars]; + } + + return [self::NOT_FOUND]; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/RegexBasedAbstract.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/RegexBasedAbstract.php new file mode 100644 index 000000000000..8823b9b25280 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Dispatcher/RegexBasedAbstract.php @@ -0,0 +1,80 @@ +staticRouteMap[$httpMethod][$uri])) { + $handler = $this->staticRouteMap[$httpMethod][$uri]; + return [self::FOUND, $handler, []]; + } + + $varRouteData = $this->variableRouteData; + if (isset($varRouteData[$httpMethod])) { + $result = $this->dispatchVariableRoute($varRouteData[$httpMethod], $uri); + if ($result[0] === self::FOUND) { + return $result; + } + } + + // For HEAD requests, attempt fallback to GET + if ($httpMethod === 'HEAD') { + if (isset($this->staticRouteMap['GET'][$uri])) { + $handler = $this->staticRouteMap['GET'][$uri]; + return [self::FOUND, $handler, []]; + } + if (isset($varRouteData['GET'])) { + $result = $this->dispatchVariableRoute($varRouteData['GET'], $uri); + if ($result[0] === self::FOUND) { + return $result; + } + } + } + + // If nothing else matches, try fallback routes + if (isset($this->staticRouteMap['*'][$uri])) { + $handler = $this->staticRouteMap['*'][$uri]; + return [self::FOUND, $handler, []]; + } + if (isset($varRouteData['*'])) { + $result = $this->dispatchVariableRoute($varRouteData['*'], $uri); + if ($result[0] === self::FOUND) { + return $result; + } + } + + // Find allowed methods for this URI by matching against all other HTTP methods as well + $allowedMethods = []; + + foreach ($this->staticRouteMap as $method => $uriMap) { + if ($method !== $httpMethod && isset($uriMap[$uri])) { + $allowedMethods[] = $method; + } + } + + foreach ($varRouteData as $method => $routeData) { + if ($method === $httpMethod) { + continue; + } + + $result = $this->dispatchVariableRoute($routeData, $uri); + if ($result[0] === self::FOUND) { + $allowedMethods[] = $method; + } + } + + // If there are no allowed methods the route simply does not exist + if ($allowedMethods) { + return [self::METHOD_NOT_ALLOWED, $allowedMethods]; + } else { + return [self::NOT_FOUND]; + } + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Route.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Route.php new file mode 100644 index 000000000000..d71ded18ad24 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/Route.php @@ -0,0 +1,38 @@ +httpMethod = $httpMethod; + $this->handler = $handler; + $this->regex = $regex; + $this->variables = $variables; + } + + /** + * Tests whether this route matches the given string. + * + * @param string $str + * + * @return bool + */ + public function matches($str) { + $regex = '~^' . $this->regex . '$~'; + return (bool) preg_match($regex, $str); + } +} + diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/RouteCollector.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/RouteCollector.php new file mode 100644 index 000000000000..4386bbf3aacc --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/RouteCollector.php @@ -0,0 +1,46 @@ +routeParser = $routeParser; + $this->dataGenerator = $dataGenerator; + } + + /** + * Adds a route to the collection. + * + * The syntax used in the $route string depends on the used route parser. + * + * @param string|string[] $httpMethod + * @param string $route + * @param mixed $handler + */ + public function addRoute($httpMethod, $route, $handler) { + $routeDatas = $this->routeParser->parse($route); + foreach ((array) $httpMethod as $method) { + foreach ($routeDatas as $routeData) { + $this->dataGenerator->addRoute($method, $routeData, $handler); + } + } + } + + /** + * Returns the collected route data, as provided by the data generator. + * + * @return array + */ + public function getData() { + return $this->dataGenerator->getData(); + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/RouteParser.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/RouteParser.php new file mode 100644 index 000000000000..c089c3151632 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/RouteParser.php @@ -0,0 +1,36 @@ + $segment) { + if ($segment === '' && $n !== 0) { + throw new BadRouteException("Empty optional part"); + } + + $currentRoute .= $segment; + $routeDatas[] = $this->parsePlaceholders($currentRoute); + } + return $routeDatas; + } + + /** + * Parses a route string that does not contain optional segments. + */ + private function parsePlaceholders($route) { + if (!preg_match_all( + '~' . self::VARIABLE_REGEX . '~x', $route, $matches, + PREG_OFFSET_CAPTURE | PREG_SET_ORDER + )) { + return [$route]; + } + + $offset = 0; + $routeData = []; + foreach ($matches as $set) { + if ($set[0][1] > $offset) { + $routeData[] = substr($route, $offset, $set[0][1] - $offset); + } + $routeData[] = [ + $set[1][0], + isset($set[2]) ? trim($set[2][0]) : self::DEFAULT_DISPATCH_REGEX + ]; + $offset = $set[0][1] + strlen($set[0][0]); + } + + if ($offset != strlen($route)) { + $routeData[] = substr($route, $offset); + } + + return $routeData; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/bootstrap.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/bootstrap.php new file mode 100644 index 000000000000..add216c7d01f --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/src/bootstrap.php @@ -0,0 +1,12 @@ + 'FastRoute\\RouteParser\\Std', + 'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased', + 'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased', + 'routeCollector' => 'FastRoute\\RouteCollector', + ]; + + /** @var RouteCollector $routeCollector */ + $routeCollector = new $options['routeCollector']( + new $options['routeParser'], new $options['dataGenerator'] + ); + $routeDefinitionCallback($routeCollector); + + return new $options['dispatcher']($routeCollector->getData()); + } + + /** + * @param callable $routeDefinitionCallback + * @param array $options + * + * @return Dispatcher + */ + function cachedDispatcher(callable $routeDefinitionCallback, array $options = []) { + $options += [ + 'routeParser' => 'FastRoute\\RouteParser\\Std', + 'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased', + 'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased', + 'routeCollector' => 'FastRoute\\RouteCollector', + 'cacheDisabled' => false, + ]; + + if (!isset($options['cacheFile'])) { + throw new \LogicException('Must specify "cacheFile" option'); + } + + if (!$options['cacheDisabled'] && file_exists($options['cacheFile'])) { + $dispatchData = require $options['cacheFile']; + if (!is_array($dispatchData)) { + throw new \RuntimeException('Invalid cache file "' . $options['cacheFile'] . '"'); + } + return new $options['dispatcher']($dispatchData); + } + + $routeCollector = new $options['routeCollector']( + new $options['routeParser'], new $options['dataGenerator'] + ); + $routeDefinitionCallback($routeCollector); + + /** @var RouteCollector $routeCollector */ + $dispatchData = $routeCollector->getData(); + file_put_contents( + $options['cacheFile'], + ' $this->getDataGeneratorClass(), + 'dispatcher' => $this->getDispatcherClass() + ]; + } + + /** + * @dataProvider provideFoundDispatchCases + */ + public function testFoundDispatches($method, $uri, $callback, $handler, $argDict) { + $dispatcher = \FastRoute\simpleDispatcher($callback, $this->generateDispatcherOptions()); + $info = $dispatcher->dispatch($method, $uri); + $this->assertSame($dispatcher::FOUND, $info[0]); + $this->assertSame($handler, $info[1]); + $this->assertSame($argDict, $info[2]); + } + + /** + * @dataProvider provideNotFoundDispatchCases + */ + public function testNotFoundDispatches($method, $uri, $callback) { + $dispatcher = \FastRoute\simpleDispatcher($callback, $this->generateDispatcherOptions()); + $routeInfo = $dispatcher->dispatch($method, $uri); + $this->assertFalse(isset($routeInfo[1]), + "NOT_FOUND result must only contain a single element in the returned info array" + ); + $this->assertSame($dispatcher::NOT_FOUND, $routeInfo[0]); + } + + /** + * @dataProvider provideMethodNotAllowedDispatchCases + */ + public function testMethodNotAllowedDispatches($method, $uri, $callback, $availableMethods) { + $dispatcher = \FastRoute\simpleDispatcher($callback, $this->generateDispatcherOptions()); + $routeInfo = $dispatcher->dispatch($method, $uri); + $this->assertTrue(isset($routeInfo[1]), + "METHOD_NOT_ALLOWED result must return an array of allowed methods at index 1" + ); + + list($routedStatus, $methodArray) = $dispatcher->dispatch($method, $uri); + $this->assertSame($dispatcher::METHOD_NOT_ALLOWED, $routedStatus); + $this->assertSame($availableMethods, $methodArray); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Cannot use the same placeholder "test" twice + */ + public function testDuplicateVariableNameError() { + \FastRoute\simpleDispatcher(function(RouteCollector $r) { + $r->addRoute('GET', '/foo/{test}/{test:\d+}', 'handler0'); + }, $this->generateDispatcherOptions()); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Cannot register two routes matching "/user/([^/]+)" for method "GET" + */ + public function testDuplicateVariableRoute() { + \FastRoute\simpleDispatcher(function(RouteCollector $r) { + $r->addRoute('GET', '/user/{id}', 'handler0'); // oops, forgot \d+ restriction ;) + $r->addRoute('GET', '/user/{name}', 'handler1'); + }, $this->generateDispatcherOptions()); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Cannot register two routes matching "/user" for method "GET" + */ + public function testDuplicateStaticRoute() { + \FastRoute\simpleDispatcher(function(RouteCollector $r) { + $r->addRoute('GET', '/user', 'handler0'); + $r->addRoute('GET', '/user', 'handler1'); + }, $this->generateDispatcherOptions()); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Static route "/user/nikic" is shadowed by previously defined variable route "/user/([^/]+)" for method "GET" + */ + public function testShadowedStaticRoute() { + \FastRoute\simpleDispatcher(function(RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('GET', '/user/nikic', 'handler1'); + }, $this->generateDispatcherOptions()); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Regex "(en|de)" for parameter "lang" contains a capturing group + */ + public function testCapturing() { + \FastRoute\simpleDispatcher(function(RouteCollector $r) { + $r->addRoute('GET', '/{lang:(en|de)}', 'handler0'); + }, $this->generateDispatcherOptions()); + } + + public function provideFoundDispatchCases() { + $cases = []; + + // 0 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/resource/123/456', 'handler0'); + }; + + $method = 'GET'; + $uri = '/resource/123/456'; + $handler = 'handler0'; + $argDict = []; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 1 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/handler0', 'handler0'); + $r->addRoute('GET', '/handler1', 'handler1'); + $r->addRoute('GET', '/handler2', 'handler2'); + }; + + $method = 'GET'; + $uri = '/handler2'; + $handler = 'handler2'; + $argDict = []; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 2 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0'); + $r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1'); + $r->addRoute('GET', '/user/{name}', 'handler2'); + }; + + $method = 'GET'; + $uri = '/user/rdlowrey'; + $handler = 'handler2'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 3 --------------------------------------------------------------------------------------> + + // reuse $callback from #2 + + $method = 'GET'; + $uri = '/user/12345'; + $handler = 'handler1'; + $argDict = ['id' => '12345']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 4 --------------------------------------------------------------------------------------> + + // reuse $callback from #3 + + $method = 'GET'; + $uri = '/user/NaN'; + $handler = 'handler2'; + $argDict = ['name' => 'NaN']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 5 --------------------------------------------------------------------------------------> + + // reuse $callback from #4 + + $method = 'GET'; + $uri = '/user/rdlowrey/12345'; + $handler = 'handler0'; + $argDict = ['name' => 'rdlowrey', 'id' => '12345']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 6 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/user/{id:[0-9]+}', 'handler0'); + $r->addRoute('GET', '/user/12345/extension', 'handler1'); + $r->addRoute('GET', '/user/{id:[0-9]+}.{extension}', 'handler2'); + + }; + + $method = 'GET'; + $uri = '/user/12345.svg'; + $handler = 'handler2'; + $argDict = ['id' => '12345', 'extension' => 'svg']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 7 ----- Test GET method fallback on HEAD route miss ------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler1'); + $r->addRoute('GET', '/static0', 'handler2'); + $r->addRoute('GET', '/static1', 'handler3'); + $r->addRoute('HEAD', '/static1', 'handler4'); + }; + + $method = 'HEAD'; + $uri = '/user/rdlowrey'; + $handler = 'handler0'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 8 ----- Test GET method fallback on HEAD route miss ------------------------------------> + + // reuse $callback from #7 + + $method = 'HEAD'; + $uri = '/user/rdlowrey/1234'; + $handler = 'handler1'; + $argDict = ['name' => 'rdlowrey', 'id' => '1234']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 9 ----- Test GET method fallback on HEAD route miss ------------------------------------> + + // reuse $callback from #8 + + $method = 'HEAD'; + $uri = '/static0'; + $handler = 'handler2'; + $argDict = []; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 10 ---- Test existing HEAD route used if available (no fallback) -----------------------> + + // reuse $callback from #9 + + $method = 'HEAD'; + $uri = '/static1'; + $handler = 'handler4'; + $argDict = []; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 11 ---- More specified routes are not shadowed by less specific of another method ------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('POST', '/user/{name:[a-z]+}', 'handler1'); + }; + + $method = 'POST'; + $uri = '/user/rdlowrey'; + $handler = 'handler1'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 12 ---- Handler of more specific routes is used, if it occurs first --------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('POST', '/user/{name:[a-z]+}', 'handler1'); + $r->addRoute('POST', '/user/{name}', 'handler2'); + }; + + $method = 'POST'; + $uri = '/user/rdlowrey'; + $handler = 'handler1'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 13 ---- Route with constant suffix -----------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('GET', '/user/{name}/edit', 'handler1'); + }; + + $method = 'GET'; + $uri = '/user/rdlowrey/edit'; + $handler = 'handler1'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 14 ---- Handle multiple methods with the same handler ----------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute(['GET', 'POST'], '/user', 'handlerGetPost'); + $r->addRoute(['DELETE'], '/user', 'handlerDelete'); + $r->addRoute([], '/user', 'handlerNone'); + }; + + $argDict = []; + $cases[] = ['GET', '/user', $callback, 'handlerGetPost', $argDict]; + $cases[] = ['POST', '/user', $callback, 'handlerGetPost', $argDict]; + $cases[] = ['DELETE', '/user', $callback, 'handlerDelete', $argDict]; + + // 15 ---- + + $callback = function(RouteCollector $r) { + $r->addRoute('POST', '/user.json', 'handler0'); + $r->addRoute('GET', '/{entity}.json', 'handler1'); + }; + + $cases[] = ['GET', '/user.json', $callback, 'handler1', ['entity' => 'user']]; + + // 16 ---- + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '', 'handler0'); + }; + + $cases[] = ['GET', '', $callback, 'handler0', []]; + + // 17 ---- + + $callback = function(RouteCollector $r) { + $r->addRoute('HEAD', '/a/{foo}', 'handler0'); + $r->addRoute('GET', '/b/{foo}', 'handler1'); + }; + + $cases[] = ['HEAD', '/b/bar', $callback, 'handler1', ['foo' => 'bar']]; + + // 18 ---- + + $callback = function(RouteCollector $r) { + $r->addRoute('HEAD', '/a', 'handler0'); + $r->addRoute('GET', '/b', 'handler1'); + }; + + $cases[] = ['HEAD', '/b', $callback, 'handler1', []]; + + // 19 ---- + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/foo', 'handler0'); + $r->addRoute('HEAD', '/{bar}', 'handler1'); + }; + + $cases[] = ['HEAD', '/foo', $callback, 'handler1', ['bar' => 'foo']]; + + // 20 ---- + + $callback = function(RouteCollector $r) { + $r->addRoute('*', '/user', 'handler0'); + $r->addRoute('*', '/{user}', 'handler1'); + $r->addRoute('GET', '/user', 'handler2'); + }; + + $cases[] = ['GET', '/user', $callback, 'handler2', []]; + + // 21 ---- + + $callback = function(RouteCollector $r) { + $r->addRoute('*', '/user', 'handler0'); + $r->addRoute('GET', '/user', 'handler1'); + }; + + $cases[] = ['POST', '/user', $callback, 'handler0', []]; + + // 22 ---- + + $cases[] = ['HEAD', '/user', $callback, 'handler1', []]; + + // 23 ---- + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/{bar}', 'handler0'); + $r->addRoute('*', '/foo', 'handler1'); + }; + + $cases[] = ['GET', '/foo', $callback, 'handler0', ['bar' => 'foo']]; + + // x --------------------------------------------------------------------------------------> + + return $cases; + } + + public function provideNotFoundDispatchCases() { + $cases = []; + + // 0 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/resource/123/456', 'handler0'); + }; + + $method = 'GET'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 1 --------------------------------------------------------------------------------------> + + // reuse callback from #0 + $method = 'POST'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 2 --------------------------------------------------------------------------------------> + + // reuse callback from #1 + $method = 'PUT'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 3 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/handler0', 'handler0'); + $r->addRoute('GET', '/handler1', 'handler1'); + $r->addRoute('GET', '/handler2', 'handler2'); + }; + + $method = 'GET'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 4 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0'); + $r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1'); + $r->addRoute('GET', '/user/{name}', 'handler2'); + }; + + $method = 'GET'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 5 --------------------------------------------------------------------------------------> + + // reuse callback from #4 + $method = 'GET'; + $uri = '/user/rdlowrey/12345/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 6 --------------------------------------------------------------------------------------> + + // reuse callback from #5 + $method = 'HEAD'; + + $cases[] = array($method, $uri, $callback); + + // x --------------------------------------------------------------------------------------> + + return $cases; + } + + public function provideMethodNotAllowedDispatchCases() { + $cases = []; + + // 0 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/resource/123/456', 'handler0'); + }; + + $method = 'POST'; + $uri = '/resource/123/456'; + $allowedMethods = ['GET']; + + $cases[] = [$method, $uri, $callback, $allowedMethods]; + + // 1 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/resource/123/456', 'handler0'); + $r->addRoute('POST', '/resource/123/456', 'handler1'); + $r->addRoute('PUT', '/resource/123/456', 'handler2'); + $r->addRoute('*', '/', 'handler3'); + }; + + $method = 'DELETE'; + $uri = '/resource/123/456'; + $allowedMethods = ['GET', 'POST', 'PUT']; + + $cases[] = [$method, $uri, $callback, $allowedMethods]; + + // 2 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0'); + $r->addRoute('POST', '/user/{name}/{id:[0-9]+}', 'handler1'); + $r->addRoute('PUT', '/user/{name}/{id:[0-9]+}', 'handler2'); + $r->addRoute('PATCH', '/user/{name}/{id:[0-9]+}', 'handler3'); + }; + + $method = 'DELETE'; + $uri = '/user/rdlowrey/42'; + $allowedMethods = ['GET', 'POST', 'PUT', 'PATCH']; + + $cases[] = [$method, $uri, $callback, $allowedMethods]; + + // 3 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('POST', '/user/{name}', 'handler1'); + $r->addRoute('PUT', '/user/{name:[a-z]+}', 'handler2'); + $r->addRoute('PATCH', '/user/{name:[a-z]+}', 'handler3'); + }; + + $method = 'GET'; + $uri = '/user/rdlowrey'; + $allowedMethods = ['POST', 'PUT', 'PATCH']; + + $cases[] = [$method, $uri, $callback, $allowedMethods]; + + // 4 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute(['GET', 'POST'], '/user', 'handlerGetPost'); + $r->addRoute(['DELETE'], '/user', 'handlerDelete'); + $r->addRoute([], '/user', 'handlerNone'); + }; + + $cases[] = ['PUT', '/user', $callback, ['GET', 'POST', 'DELETE']]; + + // 5 + + $callback = function(RouteCollector $r) { + $r->addRoute('POST', '/user.json', 'handler0'); + $r->addRoute('GET', '/{entity}.json', 'handler1'); + }; + + $cases[] = ['PUT', '/user.json', $callback, ['POST', 'GET']]; + + // x --------------------------------------------------------------------------------------> + + return $cases; + } + +} diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/Dispatcher/GroupCountBasedTest.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/Dispatcher/GroupCountBasedTest.php new file mode 100644 index 000000000000..74820fcaf989 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/Dispatcher/GroupCountBasedTest.php @@ -0,0 +1,13 @@ +markTestSkipped('PHP 5.6 required for MARK support'); + } + } + + protected function getDispatcherClass() { + return 'FastRoute\\Dispatcher\\MarkBased'; + } + + protected function getDataGeneratorClass() { + return 'FastRoute\\DataGenerator\\MarkBased'; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/HackTypechecker/HackTypecheckerTest.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/HackTypechecker/HackTypecheckerTest.php new file mode 100644 index 000000000000..7bc6ebb310de --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/HackTypechecker/HackTypecheckerTest.php @@ -0,0 +1,39 @@ +markTestSkipped("HHVM only"); + } + if (!version_compare(HHVM_VERSION, '3.9.0', '>=')) { + $this->markTestSkipped('classname requires HHVM 3.9+'); + } + + // The typechecker recurses the whole tree, so it makes sure + // that everything in fixtures/ is valid when this runs. + + $output = array(); + $exit_code = null; + exec( + 'hh_server --check '.escapeshellarg(__DIR__.'/../../').' 2>&1', + $output, + $exit_code + ); + if ($exit_code === self::SERVER_ALREADY_RUNNING_CODE) { + $this->assertTrue( + $recurse, + "Typechecker still running after running hh_client stop" + ); + // Server already running - 3.10 => 3.11 regression: + // https://github.com/facebook/hhvm/issues/6646 + exec('hh_client stop 2>/dev/null'); + $this->testTypechecks(/* recurse = */ false); + return; + + } + $this->assertSame(0, $exit_code, implode("\n", $output)); + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/all_options.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/all_options.php new file mode 100644 index 000000000000..05a9af231b4a --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/all_options.php @@ -0,0 +1,29 @@ + {}, + shape( + 'routeParser' => \FastRoute\RouteParser\Std::class, + 'dataGenerator' => \FastRoute\DataGenerator\GroupCountBased::class, + 'dispatcher' => \FastRoute\Dispatcher\GroupCountBased::class, + 'routeCollector' => \FastRoute\RouteCollector::class, + ), + ); +} + +function all_options_cached(): \FastRoute\Dispatcher { + return \FastRoute\cachedDispatcher( + $collector ==> {}, + shape( + 'routeParser' => \FastRoute\RouteParser\Std::class, + 'dataGenerator' => \FastRoute\DataGenerator\GroupCountBased::class, + 'dispatcher' => \FastRoute\Dispatcher\GroupCountBased::class, + 'routeCollector' => \FastRoute\RouteCollector::class, + 'cacheFile' => '/dev/null', + 'cacheDisabled' => false, + ), + ); +} diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/empty_options.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/empty_options.php new file mode 100644 index 000000000000..61eb54190d9e --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/empty_options.php @@ -0,0 +1,11 @@ + {}, shape()); +} + +function empty_options_cached(): \FastRoute\Dispatcher { + return \FastRoute\cachedDispatcher($collector ==> {}, shape()); +} diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/no_options.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/no_options.php new file mode 100644 index 000000000000..44b5422f583e --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/no_options.php @@ -0,0 +1,11 @@ + {}); +} + +function no_options_cached(): \FastRoute\Dispatcher { + return \FastRoute\cachedDispatcher($collector ==> {}); +} diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/RouteParser/StdTest.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/RouteParser/StdTest.php new file mode 100644 index 000000000000..41f194ba8b61 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/RouteParser/StdTest.php @@ -0,0 +1,147 @@ +parse($routeString); + $this->assertSame($expectedRouteDatas, $routeDatas); + } + + /** @dataProvider provideTestParseError */ + public function testParseError($routeString, $expectedExceptionMessage) { + $parser = new Std(); + $this->setExpectedException('FastRoute\\BadRouteException', $expectedExceptionMessage); + $parser->parse($routeString); + } + + public function provideTestParse() { + return [ + [ + '/test', + [ + ['/test'], + ] + ], + [ + '/test/{param}', + [ + ['/test/', ['param', '[^/]+']], + ] + ], + [ + '/te{ param }st', + [ + ['/te', ['param', '[^/]+'], 'st'] + ] + ], + [ + '/test/{param1}/test2/{param2}', + [ + ['/test/', ['param1', '[^/]+'], '/test2/', ['param2', '[^/]+']] + ] + ], + [ + '/test/{param:\d+}', + [ + ['/test/', ['param', '\d+']] + ] + ], + [ + '/test/{ param : \d{1,9} }', + [ + ['/test/', ['param', '\d{1,9}']] + ] + ], + [ + '/test[opt]', + [ + ['/test'], + ['/testopt'], + ] + ], + [ + '/test[/{param}]', + [ + ['/test'], + ['/test/', ['param', '[^/]+']], + ] + ], + [ + '/{param}[opt]', + [ + ['/', ['param', '[^/]+']], + ['/', ['param', '[^/]+'], 'opt'] + ] + ], + [ + '/test[/{name}[/{id:[0-9]+}]]', + [ + ['/test'], + ['/test/', ['name', '[^/]+']], + ['/test/', ['name', '[^/]+'], '/', ['id', '[0-9]+']], + ] + ], + [ + '', + [ + [''], + ] + ], + [ + '[test]', + [ + [''], + ['test'], + ] + ], + [ + '/{foo-bar}', + [ + ['/', ['foo-bar', '[^/]+']] + ] + ], + [ + '/{_foo:.*}', + [ + ['/', ['_foo', '.*']] + ] + ], + ]; + } + + public function provideTestParseError() { + return [ + [ + '/test[opt', + "Number of opening '[' and closing ']' does not match" + ], + [ + '/test[opt[opt2]', + "Number of opening '[' and closing ']' does not match" + ], + [ + '/testopt]', + "Number of opening '[' and closing ']' does not match" + ], + [ + '/test[]', + "Empty optional part" + ], + [ + '/test[[opt]]', + "Empty optional part" + ], + [ + '[[test]]', + "Empty optional part" + ], + [ + '/test[/opt]/required', + "Optional segments can only occur at the end of a route" + ], + ]; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/bootstrap.php b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/bootstrap.php new file mode 100644 index 000000000000..27e6d4c8fbdc --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/nikic/fast-route/test/bootstrap.php @@ -0,0 +1,11 @@ +> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`; fi + +script: + - cd ext/pimple + - if [ "$PIMPLE_EXT" == "yes" ]; then yes n | make test | tee output ; grep -E 'Tests failed +. +0' output; fi + - cd ../.. + - phpunit + +matrix: + exclude: + - php: hhvm + env: PIMPLE_EXT=yes diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/CHANGELOG b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/CHANGELOG new file mode 100644 index 000000000000..cc679972ec76 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/CHANGELOG @@ -0,0 +1,35 @@ +* 3.0.2 (2015-09-11) + + * refactored the C extension + * minor non-significant changes + +* 3.0.1 (2015-07-30) + + * simplified some code + * fixed a segfault in the C extension + +* 3.0.0 (2014-07-24) + + * removed the Pimple class alias (use Pimple\Container instead) + +* 2.1.1 (2014-07-24) + + * fixed compiler warnings for the C extension + * fixed code when dealing with circular references + +* 2.1.0 (2014-06-24) + + * moved the Pimple to Pimple\Container (with a BC layer -- Pimple is now a + deprecated alias which will be removed in Pimple 3.0) + * added Pimple\ServiceProviderInterface (and Pimple::register()) + +* 2.0.0 (2014-02-10) + + * changed extend to automatically re-assign the extended service and keep it as shared or factory + (to keep BC, extend still returns the extended service) + * changed services to be shared by default (use factory() for factory + services) + +* 1.0.0 + + * initial version diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/LICENSE b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/LICENSE new file mode 100644 index 000000000000..d7949e2fb35e --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2009-2015 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/README.rst b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/README.rst new file mode 100644 index 000000000000..93fb35a89b76 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/README.rst @@ -0,0 +1,201 @@ +Pimple +====== + +.. caution:: + + This is the documentation for Pimple 3.x. If you are using Pimple 1.x, read + the `Pimple 1.x documentation`_. Reading the Pimple 1.x code is also a good + way to learn more about how to create a simple Dependency Injection + Container (recent versions of Pimple are more focused on performance). + +Pimple is a small Dependency Injection Container for PHP. + +Installation +------------ + +Before using Pimple in your project, add it to your ``composer.json`` file: + +.. code-block:: bash + + $ ./composer.phar require pimple/pimple ~3.0 + +Alternatively, Pimple is also available as a PHP C extension: + +.. code-block:: bash + + $ git clone https://github.com/silexphp/Pimple + $ cd Pimple/ext/pimple + $ phpize + $ ./configure + $ make + $ make install + +Usage +----- + +Creating a container is a matter of creating a ``Container`` instance: + +.. code-block:: php + + use Pimple\Container; + + $container = new Container(); + +As many other dependency injection containers, Pimple manages two different +kind of data: **services** and **parameters**. + +Defining Services +~~~~~~~~~~~~~~~~~ + +A service is an object that does something as part of a larger system. Examples +of services: a database connection, a templating engine, or a mailer. Almost +any **global** object can be a service. + +Services are defined by **anonymous functions** that return an instance of an +object: + +.. code-block:: php + + // define some services + $container['session_storage'] = function ($c) { + return new SessionStorage('SESSION_ID'); + }; + + $container['session'] = function ($c) { + return new Session($c['session_storage']); + }; + +Notice that the anonymous function has access to the current container +instance, allowing references to other services or parameters. + +As objects are only created when you get them, the order of the definitions +does not matter. + +Using the defined services is also very easy: + +.. code-block:: php + + // get the session object + $session = $container['session']; + + // the above call is roughly equivalent to the following code: + // $storage = new SessionStorage('SESSION_ID'); + // $session = new Session($storage); + +Defining Factory Services +~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, each time you get a service, Pimple returns the **same instance** +of it. If you want a different instance to be returned for all calls, wrap your +anonymous function with the ``factory()`` method + +.. code-block:: php + + $container['session'] = $container->factory(function ($c) { + return new Session($c['session_storage']); + }); + +Now, each call to ``$container['session']`` returns a new instance of the +session. + +Defining Parameters +~~~~~~~~~~~~~~~~~~~ + +Defining a parameter allows to ease the configuration of your container from +the outside and to store global values: + +.. code-block:: php + + // define some parameters + $container['cookie_name'] = 'SESSION_ID'; + $container['session_storage_class'] = 'SessionStorage'; + +If you change the ``session_storage`` service definition like below: + +.. code-block:: php + + $container['session_storage'] = function ($c) { + return new $c['session_storage_class']($c['cookie_name']); + }; + +You can now easily change the cookie name by overriding the +``session_storage_class`` parameter instead of redefining the service +definition. + +Protecting Parameters +~~~~~~~~~~~~~~~~~~~~~ + +Because Pimple sees anonymous functions as service definitions, you need to +wrap anonymous functions with the ``protect()`` method to store them as +parameters: + +.. code-block:: php + + $container['random_func'] = $container->protect(function () { + return rand(); + }); + +Modifying Services after Definition +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In some cases you may want to modify a service definition after it has been +defined. You can use the ``extend()`` method to define additional code to be +run on your service just after it is created: + +.. code-block:: php + + $container['session_storage'] = function ($c) { + return new $c['session_storage_class']($c['cookie_name']); + }; + + $container->extend('session_storage', function ($storage, $c) { + $storage->...(); + + return $storage; + }); + +The first argument is the name of the service to extend, the second a function +that gets access to the object instance and the container. + +Extending a Container +~~~~~~~~~~~~~~~~~~~~~ + +If you use the same libraries over and over, you might want to reuse some +services from one project to the next one; package your services into a +**provider** by implementing ``Pimple\ServiceProviderInterface``: + +.. code-block:: php + + use Pimple\Container; + + class FooProvider implements Pimple\ServiceProviderInterface + { + public function register(Container $pimple) + { + // register some services and parameters + // on $pimple + } + } + +Then, register the provider on a Container: + +.. code-block:: php + + $pimple->register(new FooProvider()); + +Fetching the Service Creation Function +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When you access an object, Pimple automatically calls the anonymous function +that you defined, which creates the service object for you. If you want to get +raw access to this function, you can use the ``raw()`` method: + +.. code-block:: php + + $container['session'] = function ($c) { + return new Session($c['session_storage']); + }; + + $sessionFunction = $container->raw('session'); + +.. _Pimple 1.x documentation: https://github.com/silexphp/Pimple/tree/1.1 diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/composer.json b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/composer.json new file mode 100644 index 000000000000..a5268f161185 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/composer.json @@ -0,0 +1,25 @@ +{ + "name": "pimple/pimple", + "type": "library", + "description": "Pimple, a simple Dependency Injection Container", + "keywords": ["dependency injection", "container"], + "homepage": "http://pimple.sensiolabs.org", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "require": { + "php": ">=5.3.0" + }, + "autoload": { + "psr-0": { "Pimple": "src/" } + }, + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/.gitignore b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/.gitignore new file mode 100644 index 000000000000..1861088ac1f6 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/.gitignore @@ -0,0 +1,30 @@ +*.sw* +.deps +Makefile +Makefile.fragments +Makefile.global +Makefile.objects +acinclude.m4 +aclocal.m4 +build/ +config.cache +config.guess +config.h +config.h.in +config.log +config.nice +config.status +config.sub +configure +configure.in +install-sh +libtool +ltmain.sh +missing +mkinstalldirs +run-tests.php +*.loT +.libs/ +modules/ +*.la +*.lo diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/README.md b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/README.md new file mode 100644 index 000000000000..7b39eb2929ea --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/README.md @@ -0,0 +1,12 @@ +This is Pimple 2 implemented in C + +* PHP >= 5.3 +* Not tested under Windows, might work + +Install +======= + + > phpize + > ./configure + > make + > make install diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/config.m4 b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/config.m4 new file mode 100644 index 000000000000..c9ba17ddbd58 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/config.m4 @@ -0,0 +1,63 @@ +dnl $Id$ +dnl config.m4 for extension pimple + +dnl Comments in this file start with the string 'dnl'. +dnl Remove where necessary. This file will not work +dnl without editing. + +dnl If your extension references something external, use with: + +dnl PHP_ARG_WITH(pimple, for pimple support, +dnl Make sure that the comment is aligned: +dnl [ --with-pimple Include pimple support]) + +dnl Otherwise use enable: + +PHP_ARG_ENABLE(pimple, whether to enable pimple support, +dnl Make sure that the comment is aligned: +[ --enable-pimple Enable pimple support]) + +if test "$PHP_PIMPLE" != "no"; then + dnl Write more examples of tests here... + + dnl # --with-pimple -> check with-path + dnl SEARCH_PATH="/usr/local /usr" # you might want to change this + dnl SEARCH_FOR="/include/pimple.h" # you most likely want to change this + dnl if test -r $PHP_PIMPLE/$SEARCH_FOR; then # path given as parameter + dnl PIMPLE_DIR=$PHP_PIMPLE + dnl else # search default path list + dnl AC_MSG_CHECKING([for pimple files in default path]) + dnl for i in $SEARCH_PATH ; do + dnl if test -r $i/$SEARCH_FOR; then + dnl PIMPLE_DIR=$i + dnl AC_MSG_RESULT(found in $i) + dnl fi + dnl done + dnl fi + dnl + dnl if test -z "$PIMPLE_DIR"; then + dnl AC_MSG_RESULT([not found]) + dnl AC_MSG_ERROR([Please reinstall the pimple distribution]) + dnl fi + + dnl # --with-pimple -> add include path + dnl PHP_ADD_INCLUDE($PIMPLE_DIR/include) + + dnl # --with-pimple -> check for lib and symbol presence + dnl LIBNAME=pimple # you may want to change this + dnl LIBSYMBOL=pimple # you most likely want to change this + + dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, + dnl [ + dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $PIMPLE_DIR/lib, PIMPLE_SHARED_LIBADD) + dnl AC_DEFINE(HAVE_PIMPLELIB,1,[ ]) + dnl ],[ + dnl AC_MSG_ERROR([wrong pimple lib version or lib not found]) + dnl ],[ + dnl -L$PIMPLE_DIR/lib -lm + dnl ]) + dnl + dnl PHP_SUBST(PIMPLE_SHARED_LIBADD) + + PHP_NEW_EXTENSION(pimple, pimple.c, $ext_shared) +fi diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/config.w32 b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/config.w32 new file mode 100644 index 000000000000..39857b3254be --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/config.w32 @@ -0,0 +1,13 @@ +// $Id$ +// vim:ft=javascript + +// If your extension references something external, use ARG_WITH +// ARG_WITH("pimple", "for pimple support", "no"); + +// Otherwise, use ARG_ENABLE +// ARG_ENABLE("pimple", "enable pimple support", "no"); + +if (PHP_PIMPLE != "no") { + EXTENSION("pimple", "pimple.c"); +} + diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/php_pimple.h b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/php_pimple.h new file mode 100644 index 000000000000..49431f08a846 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/php_pimple.h @@ -0,0 +1,121 @@ + +/* + * This file is part of Pimple. + * + * Copyright (c) 2014 Fabien Potencier + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef PHP_PIMPLE_H +#define PHP_PIMPLE_H + +extern zend_module_entry pimple_module_entry; +#define phpext_pimple_ptr &pimple_module_entry + +#ifdef PHP_WIN32 +# define PHP_PIMPLE_API __declspec(dllexport) +#elif defined(__GNUC__) && __GNUC__ >= 4 +# define PHP_PIMPLE_API __attribute__ ((visibility("default"))) +#else +# define PHP_PIMPLE_API +#endif + +#ifdef ZTS +#include "TSRM.h" +#endif + +#define PIMPLE_VERSION "3.0.2" +#define PIMPLE_NS "Pimple" + +#define PIMPLE_DEFAULT_ZVAL_CACHE_NUM 5 +#define PIMPLE_DEFAULT_ZVAL_VALUES_NUM 10 + +zend_module_entry *get_module(void); + +PHP_MINIT_FUNCTION(pimple); +PHP_MINFO_FUNCTION(pimple); + +PHP_METHOD(Pimple, __construct); +PHP_METHOD(Pimple, factory); +PHP_METHOD(Pimple, protect); +PHP_METHOD(Pimple, raw); +PHP_METHOD(Pimple, extend); +PHP_METHOD(Pimple, keys); +PHP_METHOD(Pimple, register); +PHP_METHOD(Pimple, offsetSet); +PHP_METHOD(Pimple, offsetUnset); +PHP_METHOD(Pimple, offsetGet); +PHP_METHOD(Pimple, offsetExists); + +PHP_METHOD(PimpleClosure, invoker); + +typedef struct _pimple_bucket_value { + zval *value; /* Must be the first element */ + zval *raw; + zend_object_handle handle_num; + enum { + PIMPLE_IS_PARAM = 0, + PIMPLE_IS_SERVICE = 2 + } type; + zend_bool initialized; + zend_fcall_info_cache fcc; +} pimple_bucket_value; + +typedef struct _pimple_object { + zend_object zobj; + HashTable values; + HashTable factories; + HashTable protected; +} pimple_object; + +typedef struct _pimple_closure_object { + zend_object zobj; + zval *callable; + zval *factory; +} pimple_closure_object; + +static const char sensiolabs_logo[] = ""; + +static int pimple_zval_to_pimpleval(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC); +static int pimple_zval_is_valid_callback(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC); + +static void pimple_bucket_dtor(pimple_bucket_value *bucket); +static void pimple_free_bucket(pimple_bucket_value *bucket); + +static zval *pimple_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC); +static void pimple_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC); +static int pimple_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC); +static void pimple_object_unset_dimension(zval *object, zval *offset TSRMLS_DC); +static zend_object_value pimple_object_create(zend_class_entry *ce TSRMLS_DC); +static void pimple_free_object_storage(pimple_object *obj TSRMLS_DC); + +static void pimple_closure_free_object_storage(pimple_closure_object *obj TSRMLS_DC); +static zend_object_value pimple_closure_object_create(zend_class_entry *ce TSRMLS_DC); +static zend_function *pimple_closure_get_constructor(zval * TSRMLS_DC); +static int pimple_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC); + +#ifdef ZTS +#define PIMPLE_G(v) TSRMG(pimple_globals_id, zend_pimple_globals *, v) +#else +#define PIMPLE_G(v) (pimple_globals.v) +#endif + +#endif /* PHP_PIMPLE_H */ + diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/pimple.c b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/pimple.c new file mode 100644 index 000000000000..239c01d683dd --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/pimple.c @@ -0,0 +1,922 @@ + +/* + * This file is part of Pimple. + * + * Copyright (c) 2014 Fabien Potencier + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_ini.h" +#include "ext/standard/info.h" +#include "php_pimple.h" +#include "pimple_compat.h" +#include "zend_interfaces.h" +#include "zend.h" +#include "Zend/zend_closures.h" +#include "ext/spl/spl_exceptions.h" +#include "Zend/zend_exceptions.h" +#include "main/php_output.h" +#include "SAPI.h" + +static zend_class_entry *pimple_ce; +static zend_object_handlers pimple_object_handlers; +static zend_class_entry *pimple_closure_ce; +static zend_class_entry *pimple_serviceprovider_ce; +static zend_object_handlers pimple_closure_object_handlers; +static zend_internal_function pimple_closure_invoker_function; + +#define FETCH_DIM_HANDLERS_VARS pimple_object *pimple_obj = NULL; \ + ulong index; \ + pimple_obj = (pimple_object *)zend_object_store_get_object(object TSRMLS_CC); \ + +#define PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS do { \ + if (ce != pimple_ce) { \ + zend_hash_find(&ce->function_table, ZEND_STRS("offsetget"), (void **)&function); \ + if (function->common.scope != ce) { /* if the function is not defined in this actual class */ \ + pimple_object_handlers.read_dimension = pimple_object_read_dimension; /* then overwrite the handler to use custom one */ \ + } \ + zend_hash_find(&ce->function_table, ZEND_STRS("offsetset"), (void **)&function); \ + if (function->common.scope != ce) { \ + pimple_object_handlers.write_dimension = pimple_object_write_dimension; \ + } \ + zend_hash_find(&ce->function_table, ZEND_STRS("offsetexists"), (void **)&function); \ + if (function->common.scope != ce) { \ + pimple_object_handlers.has_dimension = pimple_object_has_dimension; \ + } \ + zend_hash_find(&ce->function_table, ZEND_STRS("offsetunset"), (void **)&function); \ + if (function->common.scope != ce) { \ + pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \ + } \ + } else { \ + pimple_object_handlers.read_dimension = pimple_object_read_dimension; \ + pimple_object_handlers.write_dimension = pimple_object_write_dimension; \ + pimple_object_handlers.has_dimension = pimple_object_has_dimension; \ + pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \ + }\ + } while(0); + +#define PIMPLE_CALL_CB do { \ + zend_fcall_info_argn(&fci TSRMLS_CC, 1, &object); \ + fci.size = sizeof(fci); \ + fci.object_ptr = retval->fcc.object_ptr; \ + fci.function_name = retval->value; \ + fci.no_separation = 1; \ + fci.retval_ptr_ptr = &retval_ptr_ptr; \ +\ + zend_call_function(&fci, &retval->fcc TSRMLS_CC); \ + efree(fci.params); \ + if (EG(exception)) { \ + return EG(uninitialized_zval_ptr); \ + } \ + } while(0); + +ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 0) +ZEND_ARG_ARRAY_INFO(0, value, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetset, 0, 0, 2) +ZEND_ARG_INFO(0, offset) +ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetget, 0, 0, 1) +ZEND_ARG_INFO(0, offset) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetexists, 0, 0, 1) +ZEND_ARG_INFO(0, offset) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetunset, 0, 0, 1) +ZEND_ARG_INFO(0, offset) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_factory, 0, 0, 1) +ZEND_ARG_INFO(0, callable) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_protect, 0, 0, 1) +ZEND_ARG_INFO(0, callable) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_raw, 0, 0, 1) +ZEND_ARG_INFO(0, id) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_extend, 0, 0, 2) +ZEND_ARG_INFO(0, id) +ZEND_ARG_INFO(0, callable) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_keys, 0, 0, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_register, 0, 0, 1) +ZEND_ARG_OBJ_INFO(0, provider, Pimple\\ServiceProviderInterface, 0) +ZEND_ARG_ARRAY_INFO(0, values, 1) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_serviceprovider_register, 0, 0, 1) +ZEND_ARG_OBJ_INFO(0, pimple, Pimple\\Container, 0) +ZEND_END_ARG_INFO() + +static const zend_function_entry pimple_ce_functions[] = { + PHP_ME(Pimple, __construct, arginfo___construct, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, factory, arginfo_factory, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, protect, arginfo_protect, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, raw, arginfo_raw, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, extend, arginfo_extend, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, keys, arginfo_keys, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, register, arginfo_register, ZEND_ACC_PUBLIC) + + PHP_ME(Pimple, offsetSet, arginfo_offsetset, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, offsetGet, arginfo_offsetget, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, offsetExists, arginfo_offsetexists, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, offsetUnset, arginfo_offsetunset, ZEND_ACC_PUBLIC) + PHP_FE_END +}; + +static const zend_function_entry pimple_serviceprovider_iface_ce_functions[] = { + PHP_ABSTRACT_ME(ServiceProviderInterface, register, arginfo_serviceprovider_register) + PHP_FE_END +}; + +static void pimple_closure_free_object_storage(pimple_closure_object *obj TSRMLS_DC) +{ + zend_object_std_dtor(&obj->zobj TSRMLS_CC); + if (obj->factory) { + zval_ptr_dtor(&obj->factory); + } + if (obj->callable) { + zval_ptr_dtor(&obj->callable); + } + efree(obj); +} + +static void pimple_free_object_storage(pimple_object *obj TSRMLS_DC) +{ + zend_hash_destroy(&obj->factories); + zend_hash_destroy(&obj->protected); + zend_hash_destroy(&obj->values); + zend_object_std_dtor(&obj->zobj TSRMLS_CC); + efree(obj); +} + +static void pimple_free_bucket(pimple_bucket_value *bucket) +{ + if (bucket->raw) { + zval_ptr_dtor(&bucket->raw); + } +} + +static zend_object_value pimple_closure_object_create(zend_class_entry *ce TSRMLS_DC) +{ + zend_object_value retval; + pimple_closure_object *pimple_closure_obj = NULL; + + pimple_closure_obj = ecalloc(1, sizeof(pimple_closure_object)); + ZEND_OBJ_INIT(&pimple_closure_obj->zobj, ce); + + pimple_closure_object_handlers.get_constructor = pimple_closure_get_constructor; + retval.handlers = &pimple_closure_object_handlers; + retval.handle = zend_objects_store_put(pimple_closure_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_closure_free_object_storage, NULL TSRMLS_CC); + + return retval; +} + +static zend_function *pimple_closure_get_constructor(zval *obj TSRMLS_DC) +{ + zend_error(E_ERROR, "Pimple\\ContainerClosure is an internal class and cannot be instantiated"); + + return NULL; +} + +static int pimple_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC) +{ + *zobj_ptr = obj; + *ce_ptr = Z_OBJCE_P(obj); + *fptr_ptr = (zend_function *)&pimple_closure_invoker_function; + + return SUCCESS; +} + +static zend_object_value pimple_object_create(zend_class_entry *ce TSRMLS_DC) +{ + zend_object_value retval; + pimple_object *pimple_obj = NULL; + zend_function *function = NULL; + + pimple_obj = emalloc(sizeof(pimple_object)); + ZEND_OBJ_INIT(&pimple_obj->zobj, ce); + + PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS + + retval.handlers = &pimple_object_handlers; + retval.handle = zend_objects_store_put(pimple_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_free_object_storage, NULL TSRMLS_CC); + + zend_hash_init(&pimple_obj->factories, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0); + zend_hash_init(&pimple_obj->protected, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0); + zend_hash_init(&pimple_obj->values, PIMPLE_DEFAULT_ZVAL_VALUES_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0); + + return retval; +} + +static void pimple_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC) +{ + FETCH_DIM_HANDLERS_VARS + + pimple_bucket_value pimple_value = {0}, *found_value = NULL; + ulong hash; + + pimple_zval_to_pimpleval(value, &pimple_value TSRMLS_CC); + + if (!offset) {/* $p[] = 'foo' when not overloaded */ + zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL); + Z_ADDREF_P(value); + return; + } + + switch (Z_TYPE_P(offset)) { + case IS_STRING: + hash = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + zend_hash_quick_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void **)&found_value); + if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) { + pimple_free_bucket(&pimple_value); + zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot override frozen service \"%s\".", Z_STRVAL_P(offset)); + return; + } + if (zend_hash_quick_update(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) { + pimple_free_bucket(&pimple_value); + return; + } + Z_ADDREF_P(value); + break; + case IS_DOUBLE: + case IS_BOOL: + case IS_LONG: + if (Z_TYPE_P(offset) == IS_DOUBLE) { + index = (ulong)Z_DVAL_P(offset); + } else { + index = Z_LVAL_P(offset); + } + zend_hash_index_find(&pimple_obj->values, index, (void **)&found_value); + if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) { + pimple_free_bucket(&pimple_value); + zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot override frozen service \"%ld\".", index); + return; + } + if (zend_hash_index_update(&pimple_obj->values, index, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) { + pimple_free_bucket(&pimple_value); + return; + } + Z_ADDREF_P(value); + break; + case IS_NULL: /* $p[] = 'foo' when overloaded */ + zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL); + Z_ADDREF_P(value); + break; + default: + pimple_free_bucket(&pimple_value); + zend_error(E_WARNING, "Unsupported offset type"); + } +} + +static void pimple_object_unset_dimension(zval *object, zval *offset TSRMLS_DC) +{ + FETCH_DIM_HANDLERS_VARS + + switch (Z_TYPE_P(offset)) { + case IS_STRING: + zend_symtable_del(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + zend_symtable_del(&pimple_obj->factories, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + zend_symtable_del(&pimple_obj->protected, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + break; + case IS_DOUBLE: + case IS_BOOL: + case IS_LONG: + if (Z_TYPE_P(offset) == IS_DOUBLE) { + index = (ulong)Z_DVAL_P(offset); + } else { + index = Z_LVAL_P(offset); + } + zend_hash_index_del(&pimple_obj->values, index); + zend_hash_index_del(&pimple_obj->factories, index); + zend_hash_index_del(&pimple_obj->protected, index); + break; + default: + zend_error(E_WARNING, "Unsupported offset type"); + } +} + +static int pimple_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC) +{ + FETCH_DIM_HANDLERS_VARS + + pimple_bucket_value *retval = NULL; + + switch (Z_TYPE_P(offset)) { + case IS_STRING: + if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == SUCCESS) { + switch (check_empty) { + case 0: /* isset */ + return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;) */ + case 1: /* empty */ + default: + return zend_is_true(retval->value); + } + } + return 0; + break; + case IS_DOUBLE: + case IS_BOOL: + case IS_LONG: + if (Z_TYPE_P(offset) == IS_DOUBLE) { + index = (ulong)Z_DVAL_P(offset); + } else { + index = Z_LVAL_P(offset); + } + if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == SUCCESS) { + switch (check_empty) { + case 0: /* isset */ + return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;)*/ + case 1: /* empty */ + default: + return zend_is_true(retval->value); + } + } + return 0; + break; + default: + zend_error(E_WARNING, "Unsupported offset type"); + return 0; + } +} + +static zval *pimple_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) +{ + FETCH_DIM_HANDLERS_VARS + + pimple_bucket_value *retval = NULL; + zend_fcall_info fci = {0}; + zval *retval_ptr_ptr = NULL; + + switch (Z_TYPE_P(offset)) { + case IS_STRING: + if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == FAILURE) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" is not defined.", Z_STRVAL_P(offset)); + return EG(uninitialized_zval_ptr); + } + break; + case IS_DOUBLE: + case IS_BOOL: + case IS_LONG: + if (Z_TYPE_P(offset) == IS_DOUBLE) { + index = (ulong)Z_DVAL_P(offset); + } else { + index = Z_LVAL_P(offset); + } + if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == FAILURE) { + return EG(uninitialized_zval_ptr); + } + break; + case IS_NULL: /* $p[][3] = 'foo' first dim access */ + return EG(uninitialized_zval_ptr); + break; + default: + zend_error(E_WARNING, "Unsupported offset type"); + return EG(uninitialized_zval_ptr); + } + + if(retval->type == PIMPLE_IS_PARAM) { + return retval->value; + } + + if (zend_hash_index_exists(&pimple_obj->protected, retval->handle_num)) { + /* Service is protected, return the value every time */ + return retval->value; + } + + if (zend_hash_index_exists(&pimple_obj->factories, retval->handle_num)) { + /* Service is a factory, call it everytime and never cache its result */ + PIMPLE_CALL_CB + Z_DELREF_P(retval_ptr_ptr); /* fetch dim addr will increment refcount */ + return retval_ptr_ptr; + } + + if (retval->initialized == 1) { + /* Service has already been called, return its cached value */ + return retval->value; + } + + ALLOC_INIT_ZVAL(retval->raw); + MAKE_COPY_ZVAL(&retval->value, retval->raw); + + PIMPLE_CALL_CB + + retval->initialized = 1; + zval_ptr_dtor(&retval->value); + retval->value = retval_ptr_ptr; + + return retval->value; +} + +static int pimple_zval_is_valid_callback(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC) +{ + if (Z_TYPE_P(_zval) != IS_OBJECT) { + return FAILURE; + } + + if (_pimple_bucket_value->fcc.called_scope) { + return SUCCESS; + } + + if (Z_OBJ_HANDLER_P(_zval, get_closure) && Z_OBJ_HANDLER_P(_zval, get_closure)(_zval, &_pimple_bucket_value->fcc.calling_scope, &_pimple_bucket_value->fcc.function_handler, &_pimple_bucket_value->fcc.object_ptr TSRMLS_CC) == SUCCESS) { + _pimple_bucket_value->fcc.called_scope = _pimple_bucket_value->fcc.calling_scope; + return SUCCESS; + } else { + return FAILURE; + } +} + +static int pimple_zval_to_pimpleval(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC) +{ + _pimple_bucket_value->value = _zval; + + if (Z_TYPE_P(_zval) != IS_OBJECT) { + return PIMPLE_IS_PARAM; + } + + if (pimple_zval_is_valid_callback(_zval, _pimple_bucket_value TSRMLS_CC) == SUCCESS) { + _pimple_bucket_value->type = PIMPLE_IS_SERVICE; + _pimple_bucket_value->handle_num = Z_OBJ_HANDLE_P(_zval); + } + + return PIMPLE_IS_SERVICE; +} + +static void pimple_bucket_dtor(pimple_bucket_value *bucket) +{ + zval_ptr_dtor(&bucket->value); + pimple_free_bucket(bucket); +} + +PHP_METHOD(Pimple, protect) +{ + zval *protected = NULL; + pimple_object *pobj = NULL; + pimple_bucket_value bucket = {0}; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &protected) == FAILURE) { + return; + } + + if (pimple_zval_is_valid_callback(protected, &bucket TSRMLS_CC) == FAILURE) { + pimple_free_bucket(&bucket); + zend_throw_exception(spl_ce_InvalidArgumentException, "Callable is not a Closure or invokable object.", 0 TSRMLS_CC); + return; + } + + pimple_zval_to_pimpleval(protected, &bucket TSRMLS_CC); + pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC); + + if (zend_hash_index_update(&pobj->protected, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) { + Z_ADDREF_P(protected); + RETURN_ZVAL(protected, 1 , 0); + } else { + pimple_free_bucket(&bucket); + } + RETURN_FALSE; +} + +PHP_METHOD(Pimple, raw) +{ + zval *offset = NULL; + pimple_object *pobj = NULL; + pimple_bucket_value *value = NULL; + ulong index; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { + return; + } + + pobj = zend_object_store_get_object(getThis() TSRMLS_CC); + + switch (Z_TYPE_P(offset)) { + case IS_STRING: + if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" is not defined.", Z_STRVAL_P(offset)); + RETURN_NULL(); + } + break; + case IS_DOUBLE: + case IS_BOOL: + case IS_LONG: + if (Z_TYPE_P(offset) == IS_DOUBLE) { + index = (ulong)Z_DVAL_P(offset); + } else { + index = Z_LVAL_P(offset); + } + if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) { + RETURN_NULL(); + } + break; + case IS_NULL: + default: + zend_error(E_WARNING, "Unsupported offset type"); + } + + if (value->raw) { + RETVAL_ZVAL(value->raw, 1, 0); + } else { + RETVAL_ZVAL(value->value, 1, 0); + } +} + +PHP_METHOD(Pimple, extend) +{ + zval *offset = NULL, *callable = NULL, *pimple_closure_obj = NULL; + pimple_bucket_value bucket = {0}, *value = NULL; + pimple_object *pobj = NULL; + pimple_closure_object *pcobj = NULL; + ulong index; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &callable) == FAILURE) { + return; + } + + pobj = zend_object_store_get_object(getThis() TSRMLS_CC); + + switch (Z_TYPE_P(offset)) { + case IS_STRING: + if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" is not defined.", Z_STRVAL_P(offset)); + RETURN_NULL(); + } + if (value->type != PIMPLE_IS_SERVICE) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" does not contain an object definition.", Z_STRVAL_P(offset)); + RETURN_NULL(); + } + break; + case IS_DOUBLE: + case IS_BOOL: + case IS_LONG: + if (Z_TYPE_P(offset) == IS_DOUBLE) { + index = (ulong)Z_DVAL_P(offset); + } else { + index = Z_LVAL_P(offset); + } + if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%ld\" is not defined.", index); + RETURN_NULL(); + } + if (value->type != PIMPLE_IS_SERVICE) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%ld\" does not contain an object definition.", index); + RETURN_NULL(); + } + break; + case IS_NULL: + default: + zend_error(E_WARNING, "Unsupported offset type"); + } + + if (pimple_zval_is_valid_callback(callable, &bucket TSRMLS_CC) == FAILURE) { + pimple_free_bucket(&bucket); + zend_throw_exception(spl_ce_InvalidArgumentException, "Extension service definition is not a Closure or invokable object.", 0 TSRMLS_CC); + RETURN_NULL(); + } + pimple_free_bucket(&bucket); + + ALLOC_INIT_ZVAL(pimple_closure_obj); + object_init_ex(pimple_closure_obj, pimple_closure_ce); + + pcobj = zend_object_store_get_object(pimple_closure_obj TSRMLS_CC); + pcobj->callable = callable; + pcobj->factory = value->value; + Z_ADDREF_P(callable); + Z_ADDREF_P(value->value); + + if (zend_hash_index_exists(&pobj->factories, value->handle_num)) { + pimple_zval_to_pimpleval(pimple_closure_obj, &bucket TSRMLS_CC); + zend_hash_index_del(&pobj->factories, value->handle_num); + zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL); + Z_ADDREF_P(pimple_closure_obj); + } + + pimple_object_write_dimension(getThis(), offset, pimple_closure_obj TSRMLS_CC); + + RETVAL_ZVAL(pimple_closure_obj, 1, 1); +} + +PHP_METHOD(Pimple, keys) +{ + HashPosition pos; + pimple_object *pobj = NULL; + zval **value = NULL; + zval *endval = NULL; + char *str_index = NULL; + int str_len; + ulong num_index; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + pobj = zend_object_store_get_object(getThis() TSRMLS_CC); + array_init_size(return_value, zend_hash_num_elements(&pobj->values)); + + zend_hash_internal_pointer_reset_ex(&pobj->values, &pos); + + while(zend_hash_get_current_data_ex(&pobj->values, (void **)&value, &pos) == SUCCESS) { + MAKE_STD_ZVAL(endval); + switch (zend_hash_get_current_key_ex(&pobj->values, &str_index, (uint *)&str_len, &num_index, 0, &pos)) { + case HASH_KEY_IS_STRING: + ZVAL_STRINGL(endval, str_index, str_len - 1, 1); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL); + break; + case HASH_KEY_IS_LONG: + ZVAL_LONG(endval, num_index); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL); + break; + } + zend_hash_move_forward_ex(&pobj->values, &pos); + } +} + +PHP_METHOD(Pimple, factory) +{ + zval *factory = NULL; + pimple_object *pobj = NULL; + pimple_bucket_value bucket = {0}; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &factory) == FAILURE) { + return; + } + + if (pimple_zval_is_valid_callback(factory, &bucket TSRMLS_CC) == FAILURE) { + pimple_free_bucket(&bucket); + zend_throw_exception(spl_ce_InvalidArgumentException, "Service definition is not a Closure or invokable object.", 0 TSRMLS_CC); + return; + } + + pimple_zval_to_pimpleval(factory, &bucket TSRMLS_CC); + pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC); + + if (zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) { + Z_ADDREF_P(factory); + RETURN_ZVAL(factory, 1 , 0); + } else { + pimple_free_bucket(&bucket); + } + + RETURN_FALSE; +} + +PHP_METHOD(Pimple, offsetSet) +{ + zval *offset = NULL, *value = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &value) == FAILURE) { + return; + } + + pimple_object_write_dimension(getThis(), offset, value TSRMLS_CC); +} + +PHP_METHOD(Pimple, offsetGet) +{ + zval *offset = NULL, *retval = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { + return; + } + + retval = pimple_object_read_dimension(getThis(), offset, 0 TSRMLS_CC); + + RETVAL_ZVAL(retval, 1, 0); +} + +PHP_METHOD(Pimple, offsetUnset) +{ + zval *offset = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { + return; + } + + pimple_object_unset_dimension(getThis(), offset TSRMLS_CC); +} + +PHP_METHOD(Pimple, offsetExists) +{ + zval *offset = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { + return; + } + + RETVAL_BOOL(pimple_object_has_dimension(getThis(), offset, 1 TSRMLS_CC)); +} + +PHP_METHOD(Pimple, register) +{ + zval *provider; + zval **data; + zval *retval = NULL; + zval key; + + HashTable *array = NULL; + HashPosition pos; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|h", &provider, pimple_serviceprovider_ce, &array) == FAILURE) { + return; + } + + RETVAL_ZVAL(getThis(), 1, 0); + + zend_call_method_with_1_params(&provider, Z_OBJCE_P(provider), NULL, "register", &retval, getThis()); + + if (retval) { + zval_ptr_dtor(&retval); + } + + if (!array) { + return; + } + + zend_hash_internal_pointer_reset_ex(array, &pos); + + while(zend_hash_get_current_data_ex(array, (void **)&data, &pos) == SUCCESS) { + zend_hash_get_current_key_zval_ex(array, &key, &pos); + pimple_object_write_dimension(getThis(), &key, *data TSRMLS_CC); + zend_hash_move_forward_ex(array, &pos); + } +} + +PHP_METHOD(Pimple, __construct) +{ + zval *values = NULL, **pData = NULL, offset; + HashPosition pos; + char *str_index = NULL; + zend_uint str_length; + ulong num_index; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &values) == FAILURE || !values) { + return; + } + + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos); + while (zend_hash_has_more_elements_ex(Z_ARRVAL_P(values), &pos) == SUCCESS) { + zend_hash_get_current_data_ex(Z_ARRVAL_P(values), (void **)&pData, &pos); + zend_hash_get_current_key_ex(Z_ARRVAL_P(values), &str_index, &str_length, &num_index, 0, &pos); + INIT_ZVAL(offset); + if (zend_hash_get_current_key_type_ex(Z_ARRVAL_P(values), &pos) == HASH_KEY_IS_LONG) { + ZVAL_LONG(&offset, num_index); + } else { + ZVAL_STRINGL(&offset, str_index, (str_length - 1), 0); + } + pimple_object_write_dimension(getThis(), &offset, *pData TSRMLS_CC); + zend_hash_move_forward_ex(Z_ARRVAL_P(values), &pos); + } +} + +/* + * This is PHP code snippet handling extend()s calls : + + $extended = function ($c) use ($callable, $factory) { + return $callable($factory($c), $c); + }; + + */ +PHP_METHOD(PimpleClosure, invoker) +{ + pimple_closure_object *pcobj = NULL; + zval *arg = NULL, *retval = NULL, *newretval = NULL; + zend_fcall_info fci = {0}; + zval **args[2]; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) { + return; + } + + pcobj = zend_object_store_get_object(getThis() TSRMLS_CC); + + fci.function_name = pcobj->factory; + args[0] = &arg; + zend_fcall_info_argp(&fci TSRMLS_CC, 1, args); + fci.retval_ptr_ptr = &retval; + fci.size = sizeof(fci); + + if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) { + efree(fci.params); + return; /* Should here return default zval */ + } + + efree(fci.params); + memset(&fci, 0, sizeof(fci)); + fci.size = sizeof(fci); + + fci.function_name = pcobj->callable; + args[0] = &retval; + args[1] = &arg; + zend_fcall_info_argp(&fci TSRMLS_CC, 2, args); + fci.retval_ptr_ptr = &newretval; + + if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) { + efree(fci.params); + zval_ptr_dtor(&retval); + return; + } + + efree(fci.params); + zval_ptr_dtor(&retval); + + RETVAL_ZVAL(newretval, 1 ,1); +} + +PHP_MINIT_FUNCTION(pimple) +{ + zend_class_entry tmp_pimple_ce, tmp_pimple_closure_ce, tmp_pimple_serviceprovider_iface_ce; + INIT_NS_CLASS_ENTRY(tmp_pimple_ce, PIMPLE_NS, "Container", pimple_ce_functions); + INIT_NS_CLASS_ENTRY(tmp_pimple_closure_ce, PIMPLE_NS, "ContainerClosure", NULL); + INIT_NS_CLASS_ENTRY(tmp_pimple_serviceprovider_iface_ce, PIMPLE_NS, "ServiceProviderInterface", pimple_serviceprovider_iface_ce_functions); + + tmp_pimple_ce.create_object = pimple_object_create; + tmp_pimple_closure_ce.create_object = pimple_closure_object_create; + + pimple_ce = zend_register_internal_class(&tmp_pimple_ce TSRMLS_CC); + zend_class_implements(pimple_ce TSRMLS_CC, 1, zend_ce_arrayaccess); + + pimple_closure_ce = zend_register_internal_class(&tmp_pimple_closure_ce TSRMLS_CC); + pimple_closure_ce->ce_flags |= ZEND_ACC_FINAL_CLASS; + + pimple_serviceprovider_ce = zend_register_internal_interface(&tmp_pimple_serviceprovider_iface_ce TSRMLS_CC); + + memcpy(&pimple_closure_object_handlers, zend_get_std_object_handlers(), sizeof(*zend_get_std_object_handlers())); + pimple_object_handlers = std_object_handlers; + pimple_closure_object_handlers.get_closure = pimple_closure_get_closure; + + pimple_closure_invoker_function.function_name = "Pimple closure internal invoker"; + pimple_closure_invoker_function.fn_flags |= ZEND_ACC_CLOSURE; + pimple_closure_invoker_function.handler = ZEND_MN(PimpleClosure_invoker); + pimple_closure_invoker_function.num_args = 1; + pimple_closure_invoker_function.required_num_args = 1; + pimple_closure_invoker_function.scope = pimple_closure_ce; + pimple_closure_invoker_function.type = ZEND_INTERNAL_FUNCTION; + pimple_closure_invoker_function.module = &pimple_module_entry; + + return SUCCESS; +} + +PHP_MINFO_FUNCTION(pimple) +{ + php_info_print_table_start(); + php_info_print_table_header(2, "SensioLabs Pimple C support", "enabled"); + php_info_print_table_row(2, "Pimple supported version", PIMPLE_VERSION); + php_info_print_table_end(); + + php_info_print_box_start(0); + php_write((void *)ZEND_STRL("SensioLabs Pimple C support developed by Julien Pauli") TSRMLS_CC); + if (!sapi_module.phpinfo_as_text) { + php_write((void *)ZEND_STRL(sensiolabs_logo) TSRMLS_CC); + } + php_info_print_box_end(); +} + +zend_module_entry pimple_module_entry = { + STANDARD_MODULE_HEADER, + "pimple", + NULL, + PHP_MINIT(pimple), + NULL, + NULL, + NULL, + PHP_MINFO(pimple), + PIMPLE_VERSION, + STANDARD_MODULE_PROPERTIES +}; + +#ifdef COMPILE_DL_PIMPLE +ZEND_GET_MODULE(pimple) +#endif diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/pimple_compat.h b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/pimple_compat.h new file mode 100644 index 000000000000..d234e174d0aa --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/pimple_compat.h @@ -0,0 +1,81 @@ + +/* + * This file is part of Pimple. + * + * Copyright (c) 2014 Fabien Potencier + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef PIMPLE_COMPAT_H_ +#define PIMPLE_COMPAT_H_ + +#include "Zend/zend_extensions.h" /* for ZEND_EXTENSION_API_NO */ + +#define PHP_5_0_X_API_NO 220040412 +#define PHP_5_1_X_API_NO 220051025 +#define PHP_5_2_X_API_NO 220060519 +#define PHP_5_3_X_API_NO 220090626 +#define PHP_5_4_X_API_NO 220100525 +#define PHP_5_5_X_API_NO 220121212 +#define PHP_5_6_X_API_NO 220131226 + +#define IS_PHP_56 ZEND_EXTENSION_API_NO == PHP_5_6_X_API_NO +#define IS_AT_LEAST_PHP_56 ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO + +#define IS_PHP_55 ZEND_EXTENSION_API_NO == PHP_5_5_X_API_NO +#define IS_AT_LEAST_PHP_55 ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO + +#define IS_PHP_54 ZEND_EXTENSION_API_NO == PHP_5_4_X_API_NO +#define IS_AT_LEAST_PHP_54 ZEND_EXTENSION_API_NO >= PHP_5_4_X_API_NO + +#define IS_PHP_53 ZEND_EXTENSION_API_NO == PHP_5_3_X_API_NO +#define IS_AT_LEAST_PHP_53 ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + +#if IS_PHP_53 +#define object_properties_init(obj, ce) do { \ + zend_hash_copy(obj->properties, &ce->default_properties, zval_copy_property_ctor(ce), NULL, sizeof(zval *)); \ + } while (0); +#endif + +#define ZEND_OBJ_INIT(obj, ce) do { \ + zend_object_std_init(obj, ce TSRMLS_CC); \ + object_properties_init((obj), (ce)); \ + } while(0); + +#if IS_PHP_53 || IS_PHP_54 +static void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos) { + Bucket *p; + + p = pos ? (*pos) : ht->pInternalPointer; + + if (!p) { + Z_TYPE_P(key) = IS_NULL; + } else if (p->nKeyLength) { + Z_TYPE_P(key) = IS_STRING; + Z_STRVAL_P(key) = estrndup(p->arKey, p->nKeyLength - 1); + Z_STRLEN_P(key) = p->nKeyLength - 1; + } else { + Z_TYPE_P(key) = IS_LONG; + Z_LVAL_P(key) = p->h; + } +} +#endif + +#endif /* PIMPLE_COMPAT_H_ */ diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/001.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/001.phpt new file mode 100644 index 000000000000..0809ea232b66 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/001.phpt @@ -0,0 +1,45 @@ +--TEST-- +Test for read_dim/write_dim handlers +--SKIPIF-- + +--FILE-- + + +--EXPECTF-- +foo +42 +foo2 +foo99 +baz +strstr \ No newline at end of file diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/002.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/002.phpt new file mode 100644 index 000000000000..7b56d2c1fe8b --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/002.phpt @@ -0,0 +1,15 @@ +--TEST-- +Test for constructor +--SKIPIF-- + +--FILE-- +'foo')); +var_dump($p[42]); +?> +--EXPECT-- +NULL +string(3) "foo" diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/003.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/003.phpt new file mode 100644 index 000000000000..a22cfa352ea6 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/003.phpt @@ -0,0 +1,16 @@ +--TEST-- +Test empty dimensions +--SKIPIF-- + +--FILE-- + +--EXPECT-- +int(42) +string(3) "bar" \ No newline at end of file diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/004.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/004.phpt new file mode 100644 index 000000000000..1e1d25136792 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/004.phpt @@ -0,0 +1,30 @@ +--TEST-- +Test has/unset dim handlers +--SKIPIF-- + +--FILE-- + +--EXPECT-- +int(42) +NULL +bool(true) +bool(false) +bool(true) +bool(true) \ No newline at end of file diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/005.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/005.phpt new file mode 100644 index 000000000000..0479ee055ded --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/005.phpt @@ -0,0 +1,27 @@ +--TEST-- +Test simple class inheritance +--SKIPIF-- + +--FILE-- +someAttr; +?> +--EXPECT-- +string(3) "hit" +foo +fooAttr \ No newline at end of file diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/006.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/006.phpt new file mode 100644 index 000000000000..cfe8a119e63a --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/006.phpt @@ -0,0 +1,51 @@ +--TEST-- +Test complex class inheritance +--SKIPIF-- + +--FILE-- + 'bar', 88 => 'baz'); + +$p = new TestPimple($defaultValues); +$p[42] = 'foo'; +var_dump($p[42]); +var_dump($p[0]); +?> +--EXPECT-- +string(13) "hit offsetset" +string(27) "hit offsetget in TestPimple" +string(25) "hit offsetget in MyPimple" +string(3) "foo" +string(27) "hit offsetget in TestPimple" +string(25) "hit offsetget in MyPimple" +string(3) "baz" \ No newline at end of file diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/007.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/007.phpt new file mode 100644 index 000000000000..5aac68380643 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/007.phpt @@ -0,0 +1,22 @@ +--TEST-- +Test for read_dim/write_dim handlers +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +foo +42 \ No newline at end of file diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/008.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/008.phpt new file mode 100644 index 000000000000..db7eeec4a113 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/008.phpt @@ -0,0 +1,29 @@ +--TEST-- +Test frozen services +--SKIPIF-- + +--FILE-- + +--EXPECTF-- diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/009.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/009.phpt new file mode 100644 index 000000000000..bb05ea296485 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/009.phpt @@ -0,0 +1,13 @@ +--TEST-- +Test service is called as callback, and only once +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +bool(true) \ No newline at end of file diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/010.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/010.phpt new file mode 100644 index 000000000000..badce0146a91 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/010.phpt @@ -0,0 +1,45 @@ +--TEST-- +Test service is called as callback for every callback type +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +callme +called +Foo::bar +array(2) { + [0]=> + string(3) "Foo" + [1]=> + string(3) "bar" +} \ No newline at end of file diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/011.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/011.phpt new file mode 100644 index 000000000000..6682ab8ebdbc --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/011.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test service callback throwing an exception +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +all right! \ No newline at end of file diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/012.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/012.phpt new file mode 100644 index 000000000000..4c6ac486dc74 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/012.phpt @@ -0,0 +1,28 @@ +--TEST-- +Test service factory +--SKIPIF-- + +--FILE-- +factory($f = function() { var_dump('called-1'); return 'ret-1';}); + +$p[] = $f; + +$p[] = function () { var_dump('called-2'); return 'ret-2'; }; + +var_dump($p[0]); +var_dump($p[0]); +var_dump($p[1]); +var_dump($p[1]); +?> +--EXPECTF-- +string(8) "called-1" +string(5) "ret-1" +string(8) "called-1" +string(5) "ret-1" +string(8) "called-2" +string(5) "ret-2" +string(5) "ret-2" \ No newline at end of file diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/013.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/013.phpt new file mode 100644 index 000000000000..f419958c5fa5 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/013.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test keys() +--SKIPIF-- + +--FILE-- +keys()); + +$p['foo'] = 'bar'; +$p[] = 'foo'; + +var_dump($p->keys()); + +unset($p['foo']); + +var_dump($p->keys()); +?> +--EXPECTF-- +array(0) { +} +array(2) { + [0]=> + string(3) "foo" + [1]=> + int(0) +} +array(1) { + [0]=> + int(0) +} \ No newline at end of file diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/014.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/014.phpt new file mode 100644 index 000000000000..ac937213ac0b --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/014.phpt @@ -0,0 +1,30 @@ +--TEST-- +Test raw() +--SKIPIF-- + +--FILE-- +raw('foo')); +var_dump($p[42]); + +unset($p['foo']); + +try { + $p->raw('foo'); + echo "expected exception"; +} catch (InvalidArgumentException $e) { } +--EXPECTF-- +string(8) "called-2" +string(5) "ret-2" +object(Closure)#%i (0) { +} +string(8) "called-2" +string(5) "ret-2" \ No newline at end of file diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/015.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/015.phpt new file mode 100644 index 000000000000..314f008ac1bb --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/015.phpt @@ -0,0 +1,17 @@ +--TEST-- +Test protect() +--SKIPIF-- + +--FILE-- +protect($f); + +var_dump($p['foo']); +--EXPECTF-- +object(Closure)#%i (0) { +} \ No newline at end of file diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/016.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/016.phpt new file mode 100644 index 000000000000..e55edb0a7a13 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/016.phpt @@ -0,0 +1,24 @@ +--TEST-- +Test extend() +--SKIPIF-- + +--FILE-- +extend(12, function ($w) { var_dump($w); return 'bar'; }); /* $callable in code above */ + +var_dump($c('param')); +--EXPECTF-- +string(5) "param" +string(3) "foo" +string(3) "bar" \ No newline at end of file diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/017.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/017.phpt new file mode 100644 index 000000000000..bac23ce09a91 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/017.phpt @@ -0,0 +1,17 @@ +--TEST-- +Test extend() with exception in service extension +--SKIPIF-- + +--FILE-- +extend(12, function ($w) { throw new BadMethodCallException; }); + +try { + $p[12]; + echo "Exception expected"; +} catch (BadMethodCallException $e) { } +--EXPECTF-- diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt new file mode 100644 index 000000000000..8f881d6ebf82 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt @@ -0,0 +1,17 @@ +--TEST-- +Test extend() with exception in service factory +--SKIPIF-- + +--FILE-- +extend(12, function ($w) { return 'foobar'; }); + +try { + $p[12]; + echo "Exception expected"; +} catch (BadMethodCallException $e) { } +--EXPECTF-- diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/018.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/018.phpt new file mode 100644 index 000000000000..27c12a14e79e --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/018.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test register() +--SKIPIF-- + +--FILE-- +register(new Foo, array(42 => 'bar')); + +var_dump($p[42]); +--EXPECTF-- +object(Pimple\Container)#1 (0) { +} +string(3) "bar" \ No newline at end of file diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/019.phpt b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/019.phpt new file mode 100644 index 000000000000..28a9aecac7f0 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/019.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test register() returns static and is a fluent interface +--SKIPIF-- + +--FILE-- +register(new Foo)); +--EXPECTF-- +bool(true) diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/bench.phpb b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/bench.phpb new file mode 100644 index 000000000000..8f983e656b52 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/bench.phpb @@ -0,0 +1,51 @@ +factory($factory); + +$p['factory'] = $factory; + +echo $p['factory']; +echo $p['factory']; +echo $p['factory']; + +} + +echo microtime(true) - $time; diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb new file mode 100644 index 000000000000..aec541f0bc8b --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb @@ -0,0 +1,25 @@ + diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/phpunit.xml.dist b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/phpunit.xml.dist new file mode 100644 index 000000000000..5c8d487fea9a --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/phpunit.xml.dist @@ -0,0 +1,14 @@ + + + + + + ./src/Pimple/Tests + + + diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Container.php b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Container.php new file mode 100644 index 000000000000..c976431e99a8 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Container.php @@ -0,0 +1,282 @@ +factories = new \SplObjectStorage(); + $this->protected = new \SplObjectStorage(); + + foreach ($values as $key => $value) { + $this->offsetSet($key, $value); + } + } + + /** + * Sets a parameter or an object. + * + * Objects must be defined as Closures. + * + * Allowing any PHP callable leads to difficult to debug problems + * as function names (strings) are callable (creating a function with + * the same name as an existing parameter would break your container). + * + * @param string $id The unique identifier for the parameter or object + * @param mixed $value The value of the parameter or a closure to define an object + * + * @throws \RuntimeException Prevent override of a frozen service + */ + public function offsetSet($id, $value) + { + if (isset($this->frozen[$id])) { + throw new \RuntimeException(sprintf('Cannot override frozen service "%s".', $id)); + } + + $this->values[$id] = $value; + $this->keys[$id] = true; + } + + /** + * Gets a parameter or an object. + * + * @param string $id The unique identifier for the parameter or object + * + * @return mixed The value of the parameter or an object + * + * @throws \InvalidArgumentException if the identifier is not defined + */ + public function offsetGet($id) + { + if (!isset($this->keys[$id])) { + throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id)); + } + + if ( + isset($this->raw[$id]) + || !is_object($this->values[$id]) + || isset($this->protected[$this->values[$id]]) + || !method_exists($this->values[$id], '__invoke') + ) { + return $this->values[$id]; + } + + if (isset($this->factories[$this->values[$id]])) { + return $this->values[$id]($this); + } + + $raw = $this->values[$id]; + $val = $this->values[$id] = $raw($this); + $this->raw[$id] = $raw; + + $this->frozen[$id] = true; + + return $val; + } + + /** + * Checks if a parameter or an object is set. + * + * @param string $id The unique identifier for the parameter or object + * + * @return bool + */ + public function offsetExists($id) + { + return isset($this->keys[$id]); + } + + /** + * Unsets a parameter or an object. + * + * @param string $id The unique identifier for the parameter or object + */ + public function offsetUnset($id) + { + if (isset($this->keys[$id])) { + if (is_object($this->values[$id])) { + unset($this->factories[$this->values[$id]], $this->protected[$this->values[$id]]); + } + + unset($this->values[$id], $this->frozen[$id], $this->raw[$id], $this->keys[$id]); + } + } + + /** + * Marks a callable as being a factory service. + * + * @param callable $callable A service definition to be used as a factory + * + * @return callable The passed callable + * + * @throws \InvalidArgumentException Service definition has to be a closure of an invokable object + */ + public function factory($callable) + { + if (!method_exists($callable, '__invoke')) { + throw new \InvalidArgumentException('Service definition is not a Closure or invokable object.'); + } + + $this->factories->attach($callable); + + return $callable; + } + + /** + * Protects a callable from being interpreted as a service. + * + * This is useful when you want to store a callable as a parameter. + * + * @param callable $callable A callable to protect from being evaluated + * + * @return callable The passed callable + * + * @throws \InvalidArgumentException Service definition has to be a closure of an invokable object + */ + public function protect($callable) + { + if (!method_exists($callable, '__invoke')) { + throw new \InvalidArgumentException('Callable is not a Closure or invokable object.'); + } + + $this->protected->attach($callable); + + return $callable; + } + + /** + * Gets a parameter or the closure defining an object. + * + * @param string $id The unique identifier for the parameter or object + * + * @return mixed The value of the parameter or the closure defining an object + * + * @throws \InvalidArgumentException if the identifier is not defined + */ + public function raw($id) + { + if (!isset($this->keys[$id])) { + throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id)); + } + + if (isset($this->raw[$id])) { + return $this->raw[$id]; + } + + return $this->values[$id]; + } + + /** + * Extends an object definition. + * + * Useful when you want to extend an existing object definition, + * without necessarily loading that object. + * + * @param string $id The unique identifier for the object + * @param callable $callable A service definition to extend the original + * + * @return callable The wrapped callable + * + * @throws \InvalidArgumentException if the identifier is not defined or not a service definition + */ + public function extend($id, $callable) + { + if (!isset($this->keys[$id])) { + throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id)); + } + + if (!is_object($this->values[$id]) || !method_exists($this->values[$id], '__invoke')) { + throw new \InvalidArgumentException(sprintf('Identifier "%s" does not contain an object definition.', $id)); + } + + if (!is_object($callable) || !method_exists($callable, '__invoke')) { + throw new \InvalidArgumentException('Extension service definition is not a Closure or invokable object.'); + } + + $factory = $this->values[$id]; + + $extended = function ($c) use ($callable, $factory) { + return $callable($factory($c), $c); + }; + + if (isset($this->factories[$factory])) { + $this->factories->detach($factory); + $this->factories->attach($extended); + } + + return $this[$id] = $extended; + } + + /** + * Returns all defined value names. + * + * @return array An array of value names + */ + public function keys() + { + return array_keys($this->values); + } + + /** + * Registers a service provider. + * + * @param ServiceProviderInterface $provider A ServiceProviderInterface instance + * @param array $values An array of values that customizes the provider + * + * @return static + */ + public function register(ServiceProviderInterface $provider, array $values = array()) + { + $provider->register($this); + + foreach ($values as $key => $value) { + $this[$key] = $value; + } + + return $this; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php new file mode 100644 index 000000000000..c004594baf04 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php @@ -0,0 +1,46 @@ +value = $value; + + return $service; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php new file mode 100644 index 000000000000..33cd4e548640 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php @@ -0,0 +1,34 @@ +factory(function () { + return new Service(); + }); + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php new file mode 100644 index 000000000000..d71b184ddf7f --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php @@ -0,0 +1,35 @@ + + */ +class Service +{ + public $value; +} diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php new file mode 100644 index 000000000000..8e5c4c73deb0 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php @@ -0,0 +1,76 @@ + + */ +class PimpleServiceProviderInterfaceTest extends \PHPUnit_Framework_TestCase +{ + public function testProvider() + { + $pimple = new Container(); + + $pimpleServiceProvider = new Fixtures\PimpleServiceProvider(); + $pimpleServiceProvider->register($pimple); + + $this->assertEquals('value', $pimple['param']); + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); + + $serviceOne = $pimple['factory']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + + $serviceTwo = $pimple['factory']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + + $this->assertNotSame($serviceOne, $serviceTwo); + } + + public function testProviderWithRegisterMethod() + { + $pimple = new Container(); + + $pimple->register(new Fixtures\PimpleServiceProvider(), array( + 'anotherParameter' => 'anotherValue', + )); + + $this->assertEquals('value', $pimple['param']); + $this->assertEquals('anotherValue', $pimple['anotherParameter']); + + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); + + $serviceOne = $pimple['factory']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + + $serviceTwo = $pimple['factory']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + + $this->assertNotSame($serviceOne, $serviceTwo); + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php new file mode 100644 index 000000000000..918f620d8841 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php @@ -0,0 +1,440 @@ + + */ +class PimpleTest extends \PHPUnit_Framework_TestCase +{ + public function testWithString() + { + $pimple = new Container(); + $pimple['param'] = 'value'; + + $this->assertEquals('value', $pimple['param']); + } + + public function testWithClosure() + { + $pimple = new Container(); + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); + } + + public function testServicesShouldBeDifferent() + { + $pimple = new Container(); + $pimple['service'] = $pimple->factory(function () { + return new Fixtures\Service(); + }); + + $serviceOne = $pimple['service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + + $serviceTwo = $pimple['service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + + $this->assertNotSame($serviceOne, $serviceTwo); + } + + public function testShouldPassContainerAsParameter() + { + $pimple = new Container(); + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + $pimple['container'] = function ($container) { + return $container; + }; + + $this->assertNotSame($pimple, $pimple['service']); + $this->assertSame($pimple, $pimple['container']); + } + + public function testIsset() + { + $pimple = new Container(); + $pimple['param'] = 'value'; + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + + $pimple['null'] = null; + + $this->assertTrue(isset($pimple['param'])); + $this->assertTrue(isset($pimple['service'])); + $this->assertTrue(isset($pimple['null'])); + $this->assertFalse(isset($pimple['non_existent'])); + } + + public function testConstructorInjection() + { + $params = array('param' => 'value'); + $pimple = new Container($params); + + $this->assertSame($params['param'], $pimple['param']); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Identifier "foo" is not defined. + */ + public function testOffsetGetValidatesKeyIsPresent() + { + $pimple = new Container(); + echo $pimple['foo']; + } + + public function testOffsetGetHonorsNullValues() + { + $pimple = new Container(); + $pimple['foo'] = null; + $this->assertNull($pimple['foo']); + } + + public function testUnset() + { + $pimple = new Container(); + $pimple['param'] = 'value'; + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + + unset($pimple['param'], $pimple['service']); + $this->assertFalse(isset($pimple['param'])); + $this->assertFalse(isset($pimple['service'])); + } + + /** + * @dataProvider serviceDefinitionProvider + */ + public function testShare($service) + { + $pimple = new Container(); + $pimple['shared_service'] = $service; + + $serviceOne = $pimple['shared_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + + $serviceTwo = $pimple['shared_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + + $this->assertSame($serviceOne, $serviceTwo); + } + + /** + * @dataProvider serviceDefinitionProvider + */ + public function testProtect($service) + { + $pimple = new Container(); + $pimple['protected'] = $pimple->protect($service); + + $this->assertSame($service, $pimple['protected']); + } + + public function testGlobalFunctionNameAsParameterValue() + { + $pimple = new Container(); + $pimple['global_function'] = 'strlen'; + $this->assertSame('strlen', $pimple['global_function']); + } + + public function testRaw() + { + $pimple = new Container(); + $pimple['service'] = $definition = $pimple->factory(function () { return 'foo'; }); + $this->assertSame($definition, $pimple->raw('service')); + } + + public function testRawHonorsNullValues() + { + $pimple = new Container(); + $pimple['foo'] = null; + $this->assertNull($pimple->raw('foo')); + } + + public function testFluentRegister() + { + $pimple = new Container(); + $this->assertSame($pimple, $pimple->register($this->getMock('Pimple\ServiceProviderInterface'))); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Identifier "foo" is not defined. + */ + public function testRawValidatesKeyIsPresent() + { + $pimple = new Container(); + $pimple->raw('foo'); + } + + /** + * @dataProvider serviceDefinitionProvider + */ + public function testExtend($service) + { + $pimple = new Container(); + $pimple['shared_service'] = function () { + return new Fixtures\Service(); + }; + $pimple['factory_service'] = $pimple->factory(function () { + return new Fixtures\Service(); + }); + + $pimple->extend('shared_service', $service); + $serviceOne = $pimple['shared_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + $serviceTwo = $pimple['shared_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + $this->assertSame($serviceOne, $serviceTwo); + $this->assertSame($serviceOne->value, $serviceTwo->value); + + $pimple->extend('factory_service', $service); + $serviceOne = $pimple['factory_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + $serviceTwo = $pimple['factory_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + $this->assertNotSame($serviceOne, $serviceTwo); + $this->assertNotSame($serviceOne->value, $serviceTwo->value); + } + + public function testExtendDoesNotLeakWithFactories() + { + if (extension_loaded('pimple')) { + $this->markTestSkipped('Pimple extension does not support this test'); + } + $pimple = new Container(); + + $pimple['foo'] = $pimple->factory(function () { return; }); + $pimple['foo'] = $pimple->extend('foo', function ($foo, $pimple) { return; }); + unset($pimple['foo']); + + $p = new \ReflectionProperty($pimple, 'values'); + $p->setAccessible(true); + $this->assertEmpty($p->getValue($pimple)); + + $p = new \ReflectionProperty($pimple, 'factories'); + $p->setAccessible(true); + $this->assertCount(0, $p->getValue($pimple)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Identifier "foo" is not defined. + */ + public function testExtendValidatesKeyIsPresent() + { + $pimple = new Container(); + $pimple->extend('foo', function () {}); + } + + public function testKeys() + { + $pimple = new Container(); + $pimple['foo'] = 123; + $pimple['bar'] = 123; + + $this->assertEquals(array('foo', 'bar'), $pimple->keys()); + } + + /** @test */ + public function settingAnInvokableObjectShouldTreatItAsFactory() + { + $pimple = new Container(); + $pimple['invokable'] = new Fixtures\Invokable(); + + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['invokable']); + } + + /** @test */ + public function settingNonInvokableObjectShouldTreatItAsParameter() + { + $pimple = new Container(); + $pimple['non_invokable'] = new Fixtures\NonInvokable(); + + $this->assertInstanceOf('Pimple\Tests\Fixtures\NonInvokable', $pimple['non_invokable']); + } + + /** + * @dataProvider badServiceDefinitionProvider + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Service definition is not a Closure or invokable object. + */ + public function testFactoryFailsForInvalidServiceDefinitions($service) + { + $pimple = new Container(); + $pimple->factory($service); + } + + /** + * @dataProvider badServiceDefinitionProvider + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Callable is not a Closure or invokable object. + */ + public function testProtectFailsForInvalidServiceDefinitions($service) + { + $pimple = new Container(); + $pimple->protect($service); + } + + /** + * @dataProvider badServiceDefinitionProvider + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Identifier "foo" does not contain an object definition. + */ + public function testExtendFailsForKeysNotContainingServiceDefinitions($service) + { + $pimple = new Container(); + $pimple['foo'] = $service; + $pimple->extend('foo', function () {}); + } + + /** + * @dataProvider badServiceDefinitionProvider + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Extension service definition is not a Closure or invokable object. + */ + public function testExtendFailsForInvalidServiceDefinitions($service) + { + $pimple = new Container(); + $pimple['foo'] = function () {}; + $pimple->extend('foo', $service); + } + + /** + * Provider for invalid service definitions. + */ + public function badServiceDefinitionProvider() + { + return array( + array(123), + array(new Fixtures\NonInvokable()), + ); + } + + /** + * Provider for service definitions. + */ + public function serviceDefinitionProvider() + { + return array( + array(function ($value) { + $service = new Fixtures\Service(); + $service->value = $value; + + return $service; + }), + array(new Fixtures\Invokable()), + ); + } + + public function testDefiningNewServiceAfterFreeze() + { + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $foo = $pimple['foo']; + + $pimple['bar'] = function () { + return 'bar'; + }; + $this->assertSame('bar', $pimple['bar']); + } + + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage Cannot override frozen service "foo". + */ + public function testOverridingServiceAfterFreeze() + { + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $foo = $pimple['foo']; + + $pimple['foo'] = function () { + return 'bar'; + }; + } + + public function testRemovingServiceAfterFreeze() + { + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $foo = $pimple['foo']; + + unset($pimple['foo']); + $pimple['foo'] = function () { + return 'bar'; + }; + $this->assertSame('bar', $pimple['foo']); + } + + public function testExtendingService() + { + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) { + return "$foo.bar"; + }); + $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) { + return "$foo.baz"; + }); + $this->assertSame('foo.bar.baz', $pimple['foo']); + } + + public function testExtendingServiceAfterOtherServiceFreeze() + { + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $pimple['bar'] = function () { + return 'bar'; + }; + $foo = $pimple['foo']; + + $pimple['bar'] = $pimple->extend('bar', function ($bar, $app) { + return "$bar.baz"; + }); + $this->assertSame('bar.baz', $pimple['bar']); + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/psr/http-message/LICENSE b/samples/server/petstore-security-test/slim/vendor/psr/http-message/LICENSE new file mode 100644 index 000000000000..c2d8e452de1b --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/psr/http-message/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014 PHP Framework Interoperability Group + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/samples/server/petstore-security-test/slim/vendor/psr/http-message/README.md b/samples/server/petstore-security-test/slim/vendor/psr/http-message/README.md new file mode 100644 index 000000000000..28185338f723 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/psr/http-message/README.md @@ -0,0 +1,13 @@ +PSR Http Message +================ + +This repository holds all interfaces/classes/traits related to +[PSR-7](http://www.php-fig.org/psr/psr-7/). + +Note that this is not a HTTP message implementation of its own. It is merely an +interface that describes a HTTP message. See the specification for more details. + +Usage +----- + +We'll certainly need some stuff in here. \ No newline at end of file diff --git a/samples/server/petstore-security-test/slim/vendor/psr/http-message/composer.json b/samples/server/petstore-security-test/slim/vendor/psr/http-message/composer.json new file mode 100644 index 000000000000..4774b6126276 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/psr/http-message/composer.json @@ -0,0 +1,25 @@ +{ + "name": "psr/http-message", + "description": "Common interface for HTTP messages", + "keywords": ["psr", "psr-7", "http", "http-message", "request", "response"], + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "require": { + "php": ">=5.3.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/psr/http-message/src/MessageInterface.php b/samples/server/petstore-security-test/slim/vendor/psr/http-message/src/MessageInterface.php new file mode 100644 index 000000000000..8f67a050e8cf --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/psr/http-message/src/MessageInterface.php @@ -0,0 +1,187 @@ +getHeaders() as $name => $values) { + * echo $name . ": " . implode(", ", $values); + * } + * + * // Emit headers iteratively: + * foreach ($message->getHeaders() as $name => $values) { + * foreach ($values as $value) { + * header(sprintf('%s: %s', $name, $value), false); + * } + * } + * + * While header names are not case-sensitive, getHeaders() will preserve the + * exact case in which headers were originally specified. + * + * @return array Returns an associative array of the message's headers. Each + * key MUST be a header name, and each value MUST be an array of strings + * for that header. + */ + public function getHeaders(); + + /** + * Checks if a header exists by the given case-insensitive name. + * + * @param string $name Case-insensitive header field name. + * @return bool Returns true if any header names match the given header + * name using a case-insensitive string comparison. Returns false if + * no matching header name is found in the message. + */ + public function hasHeader($name); + + /** + * Retrieves a message header value by the given case-insensitive name. + * + * This method returns an array of all the header values of the given + * case-insensitive header name. + * + * If the header does not appear in the message, this method MUST return an + * empty array. + * + * @param string $name Case-insensitive header field name. + * @return string[] An array of string values as provided for the given + * header. If the header does not appear in the message, this method MUST + * return an empty array. + */ + public function getHeader($name); + + /** + * Retrieves a comma-separated string of the values for a single header. + * + * This method returns all of the header values of the given + * case-insensitive header name as a string concatenated together using + * a comma. + * + * NOTE: Not all header values may be appropriately represented using + * comma concatenation. For such headers, use getHeader() instead + * and supply your own delimiter when concatenating. + * + * If the header does not appear in the message, this method MUST return + * an empty string. + * + * @param string $name Case-insensitive header field name. + * @return string A string of values as provided for the given header + * concatenated together using a comma. If the header does not appear in + * the message, this method MUST return an empty string. + */ + public function getHeaderLine($name); + + /** + * Return an instance with the provided value replacing the specified header. + * + * While header names are case-insensitive, the casing of the header will + * be preserved by this function, and returned from getHeaders(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new and/or updated header and value. + * + * @param string $name Case-insensitive header field name. + * @param string|string[] $value Header value(s). + * @return self + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withHeader($name, $value); + + /** + * Return an instance with the specified header appended with the given value. + * + * Existing values for the specified header will be maintained. The new + * value(s) will be appended to the existing list. If the header did not + * exist previously, it will be added. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new header and/or value. + * + * @param string $name Case-insensitive header field name to add. + * @param string|string[] $value Header value(s). + * @return self + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withAddedHeader($name, $value); + + /** + * Return an instance without the specified header. + * + * Header resolution MUST be done without case-sensitivity. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the named header. + * + * @param string $name Case-insensitive header field name to remove. + * @return self + */ + public function withoutHeader($name); + + /** + * Gets the body of the message. + * + * @return StreamInterface Returns the body as a stream. + */ + public function getBody(); + + /** + * Return an instance with the specified message body. + * + * The body MUST be a StreamInterface object. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return a new instance that has the + * new body stream. + * + * @param StreamInterface $body Body. + * @return self + * @throws \InvalidArgumentException When the body is not valid. + */ + public function withBody(StreamInterface $body); +} diff --git a/samples/server/petstore-security-test/slim/vendor/psr/http-message/src/RequestInterface.php b/samples/server/petstore-security-test/slim/vendor/psr/http-message/src/RequestInterface.php new file mode 100644 index 000000000000..75c802e2927d --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/psr/http-message/src/RequestInterface.php @@ -0,0 +1,129 @@ +getQuery()` + * or from the `QUERY_STRING` server param. + * + * @return array + */ + public function getQueryParams(); + + /** + * Return an instance with the specified query string arguments. + * + * These values SHOULD remain immutable over the course of the incoming + * request. They MAY be injected during instantiation, such as from PHP's + * $_GET superglobal, or MAY be derived from some other value such as the + * URI. In cases where the arguments are parsed from the URI, the data + * MUST be compatible with what PHP's parse_str() would return for + * purposes of how duplicate query parameters are handled, and how nested + * sets are handled. + * + * Setting query string arguments MUST NOT change the URI stored by the + * request, nor the values in the server params. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated query string arguments. + * + * @param array $query Array of query string arguments, typically from + * $_GET. + * @return self + */ + public function withQueryParams(array $query); + + /** + * Retrieve normalized file upload data. + * + * This method returns upload metadata in a normalized tree, with each leaf + * an instance of Psr\Http\Message\UploadedFileInterface. + * + * These values MAY be prepared from $_FILES or the message body during + * instantiation, or MAY be injected via withUploadedFiles(). + * + * @return array An array tree of UploadedFileInterface instances; an empty + * array MUST be returned if no data is present. + */ + public function getUploadedFiles(); + + /** + * Create a new instance with the specified uploaded files. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param array An array tree of UploadedFileInterface instances. + * @return self + * @throws \InvalidArgumentException if an invalid structure is provided. + */ + public function withUploadedFiles(array $uploadedFiles); + + /** + * Retrieve any parameters provided in the request body. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, this method MUST + * return the contents of $_POST. + * + * Otherwise, this method may return any results of deserializing + * the request body content; as parsing returns structured content, the + * potential types MUST be arrays or objects only. A null value indicates + * the absence of body content. + * + * @return null|array|object The deserialized body parameters, if any. + * These will typically be an array or object. + */ + public function getParsedBody(); + + /** + * Return an instance with the specified body parameters. + * + * These MAY be injected during instantiation. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, use this method + * ONLY to inject the contents of $_POST. + * + * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of + * deserializing the request body content. Deserialization/parsing returns + * structured data, and, as such, this method ONLY accepts arrays or objects, + * or a null value if nothing was available to parse. + * + * As an example, if content negotiation determines that the request data + * is a JSON payload, this method could be used to create a request + * instance with the deserialized parameters. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param null|array|object $data The deserialized body data. This will + * typically be in an array or object. + * @return self + * @throws \InvalidArgumentException if an unsupported argument type is + * provided. + */ + public function withParsedBody($data); + + /** + * Retrieve attributes derived from the request. + * + * The request "attributes" may be used to allow injection of any + * parameters derived from the request: e.g., the results of path + * match operations; the results of decrypting cookies; the results of + * deserializing non-form-encoded message bodies; etc. Attributes + * will be application and request specific, and CAN be mutable. + * + * @return array Attributes derived from the request. + */ + public function getAttributes(); + + /** + * Retrieve a single derived request attribute. + * + * Retrieves a single derived request attribute as described in + * getAttributes(). If the attribute has not been previously set, returns + * the default value as provided. + * + * This method obviates the need for a hasAttribute() method, as it allows + * specifying a default value to return if the attribute is not found. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $default Default value to return if the attribute does not exist. + * @return mixed + */ + public function getAttribute($name, $default = null); + + /** + * Return an instance with the specified derived request attribute. + * + * This method allows setting a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $value The value of the attribute. + * @return self + */ + public function withAttribute($name, $value); + + /** + * Return an instance that removes the specified derived request attribute. + * + * This method allows removing a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @return self + */ + public function withoutAttribute($name); +} diff --git a/samples/server/petstore-security-test/slim/vendor/psr/http-message/src/StreamInterface.php b/samples/server/petstore-security-test/slim/vendor/psr/http-message/src/StreamInterface.php new file mode 100644 index 000000000000..f68f391269b4 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/psr/http-message/src/StreamInterface.php @@ -0,0 +1,158 @@ + + * [user-info@]host[:port] + * + * + * If the port component is not set or is the standard port for the current + * scheme, it SHOULD NOT be included. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.2 + * @return string The URI authority, in "[user-info@]host[:port]" format. + */ + public function getAuthority(); + + /** + * Retrieve the user information component of the URI. + * + * If no user information is present, this method MUST return an empty + * string. + * + * If a user is present in the URI, this will return that value; + * additionally, if the password is also present, it will be appended to the + * user value, with a colon (":") separating the values. + * + * The trailing "@" character is not part of the user information and MUST + * NOT be added. + * + * @return string The URI user information, in "username[:password]" format. + */ + public function getUserInfo(); + + /** + * Retrieve the host component of the URI. + * + * If no host is present, this method MUST return an empty string. + * + * The value returned MUST be normalized to lowercase, per RFC 3986 + * Section 3.2.2. + * + * @see http://tools.ietf.org/html/rfc3986#section-3.2.2 + * @return string The URI host. + */ + public function getHost(); + + /** + * Retrieve the port component of the URI. + * + * If a port is present, and it is non-standard for the current scheme, + * this method MUST return it as an integer. If the port is the standard port + * used with the current scheme, this method SHOULD return null. + * + * If no port is present, and no scheme is present, this method MUST return + * a null value. + * + * If no port is present, but a scheme is present, this method MAY return + * the standard port for that scheme, but SHOULD return null. + * + * @return null|int The URI port. + */ + public function getPort(); + + /** + * Retrieve the path component of the URI. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * Normally, the empty path "" and absolute path "/" are considered equal as + * defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically + * do this normalization because in contexts with a trimmed base path, e.g. + * the front controller, this difference becomes significant. It's the task + * of the user to handle both "" and "/". + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.3. + * + * As an example, if the value should include a slash ("/") not intended as + * delimiter between path segments, that value MUST be passed in encoded + * form (e.g., "%2F") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.3 + * @return string The URI path. + */ + public function getPath(); + + /** + * Retrieve the query string of the URI. + * + * If no query string is present, this method MUST return an empty string. + * + * The leading "?" character is not part of the query and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.4. + * + * As an example, if a value in a key/value pair of the query string should + * include an ampersand ("&") not intended as a delimiter between values, + * that value MUST be passed in encoded form (e.g., "%26") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.4 + * @return string The URI query string. + */ + public function getQuery(); + + /** + * Retrieve the fragment component of the URI. + * + * If no fragment is present, this method MUST return an empty string. + * + * The leading "#" character is not part of the fragment and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.5. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.5 + * @return string The URI fragment. + */ + public function getFragment(); + + /** + * Return an instance with the specified scheme. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified scheme. + * + * Implementations MUST support the schemes "http" and "https" case + * insensitively, and MAY accommodate other schemes if required. + * + * An empty scheme is equivalent to removing the scheme. + * + * @param string $scheme The scheme to use with the new instance. + * @return self A new instance with the specified scheme. + * @throws \InvalidArgumentException for invalid or unsupported schemes. + */ + public function withScheme($scheme); + + /** + * Return an instance with the specified user information. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified user information. + * + * Password is optional, but the user information MUST include the + * user; an empty string for the user is equivalent to removing user + * information. + * + * @param string $user The user name to use for authority. + * @param null|string $password The password associated with $user. + * @return self A new instance with the specified user information. + */ + public function withUserInfo($user, $password = null); + + /** + * Return an instance with the specified host. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified host. + * + * An empty host value is equivalent to removing the host. + * + * @param string $host The hostname to use with the new instance. + * @return self A new instance with the specified host. + * @throws \InvalidArgumentException for invalid hostnames. + */ + public function withHost($host); + + /** + * Return an instance with the specified port. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified port. + * + * Implementations MUST raise an exception for ports outside the + * established TCP and UDP port ranges. + * + * A null value provided for the port is equivalent to removing the port + * information. + * + * @param null|int $port The port to use with the new instance; a null value + * removes the port information. + * @return self A new instance with the specified port. + * @throws \InvalidArgumentException for invalid ports. + */ + public function withPort($port); + + /** + * Return an instance with the specified path. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified path. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * If the path is intended to be domain-relative rather than path relative then + * it must begin with a slash ("/"). Paths not starting with a slash ("/") + * are assumed to be relative to some base path known to the application or + * consumer. + * + * Users can provide both encoded and decoded path characters. + * Implementations ensure the correct encoding as outlined in getPath(). + * + * @param string $path The path to use with the new instance. + * @return self A new instance with the specified path. + * @throws \InvalidArgumentException for invalid paths. + */ + public function withPath($path); + + /** + * Return an instance with the specified query string. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified query string. + * + * Users can provide both encoded and decoded query characters. + * Implementations ensure the correct encoding as outlined in getQuery(). + * + * An empty query string value is equivalent to removing the query string. + * + * @param string $query The query string to use with the new instance. + * @return self A new instance with the specified query string. + * @throws \InvalidArgumentException for invalid query strings. + */ + public function withQuery($query); + + /** + * Return an instance with the specified URI fragment. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified URI fragment. + * + * Users can provide both encoded and decoded fragment characters. + * Implementations ensure the correct encoding as outlined in getFragment(). + * + * An empty fragment value is equivalent to removing the fragment. + * + * @param string $fragment The fragment to use with the new instance. + * @return self A new instance with the specified fragment. + */ + public function withFragment($fragment); + + /** + * Return the string representation as a URI reference. + * + * Depending on which components of the URI are present, the resulting + * string is either a full URI or relative reference according to RFC 3986, + * Section 4.1. The method concatenates the various components of the URI, + * using the appropriate delimiters: + * + * - If a scheme is present, it MUST be suffixed by ":". + * - If an authority is present, it MUST be prefixed by "//". + * - The path can be concatenated without delimiters. But there are two + * cases where the path has to be adjusted to make the URI reference + * valid as PHP does not allow to throw an exception in __toString(): + * - If the path is rootless and an authority is present, the path MUST + * be prefixed by "/". + * - If the path is starting with more than one "/" and no authority is + * present, the starting slashes MUST be reduced to one. + * - If a query is present, it MUST be prefixed by "?". + * - If a fragment is present, it MUST be prefixed by "#". + * + * @see http://tools.ietf.org/html/rfc3986#section-4.1 + * @return string + */ + public function __toString(); +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/CONTRIBUTING.md b/samples/server/petstore-security-test/slim/vendor/slim/slim/CONTRIBUTING.md new file mode 100644 index 000000000000..9bbb6b17ca2c --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/CONTRIBUTING.md @@ -0,0 +1,20 @@ +# How to Contribute + +## Pull Requests + +1. Fork the Slim Framework repository +2. Create a new branch for each feature or improvement +3. Send a pull request from each feature branch to the **develop** branch + +It is very important to separate new features or improvements into separate feature branches, and to send a +pull request for each branch. This allows me to review and pull in new features or improvements individually. + +## Style Guide + +All pull requests must adhere to the [PSR-2 standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md). + +## Unit Testing + +All pull requests must be accompanied by passing unit tests and complete code coverage. The Slim Framework uses phpunit for testing. + +[Learn about PHPUnit](https://github.com/sebastianbergmann/phpunit/) diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/LICENSE.md b/samples/server/petstore-security-test/slim/vendor/slim/slim/LICENSE.md new file mode 100644 index 000000000000..0875f84f9057 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/LICENSE.md @@ -0,0 +1,19 @@ +Copyright (c) 2011-2016 Josh Lockhart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/README.md b/samples/server/petstore-security-test/slim/vendor/slim/slim/README.md new file mode 100644 index 000000000000..d20f3939d1c4 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/README.md @@ -0,0 +1,84 @@ +# Slim Framework + +[![Build Status](https://travis-ci.org/slimphp/Slim.svg?branch=develop)](https://travis-ci.org/slimphp/Slim) +[![Coverage Status](https://coveralls.io/repos/slimphp/Slim/badge.svg)](https://coveralls.io/r/slimphp/Slim) +[![Total Downloads](https://poser.pugx.org/slim/slim/downloads)](https://packagist.org/packages/slim/slim) +[![License](https://poser.pugx.org/slim/slim/license)](https://packagist.org/packages/slim/slim) + +Slim is a PHP micro-framework that helps you quickly write simple yet powerful web applications and APIs. + +## Installation + +It's recommended that you use [Composer](https://getcomposer.org/) to install Slim. + +```bash +$ composer require slim/slim "^3.0" +``` + +This will install Slim and all required dependencies. Slim requires PHP 5.5.0 or newer. + +## Usage + +Create an index.php file with the following contents: + +```php +get('/hello/{name}', function ($request, $response, $args) { + $response->write("Hello, " . $args['name']); + return $response; +}); + +$app->run(); +``` + +You may quickly test this using the built-in PHP server: +```bash +$ php -S localhost:8000 +``` + +Going to http://localhost:8000/hello/world will now display "Hello, world". + +For more information on how to configure your web server, see the [Documentation](http://www.slimframework.com/docs/start/web-servers.html). + +## Tests + +To execute the test suite, you'll need phpunit. + +```bash +$ phpunit +``` + +## Contributing + +Please see [CONTRIBUTING](CONTRIBUTING.md) for details. + +## Learn More + +Learn more at these links: + +- [Website](http://www.slimframework.com) +- [Documentation](http://www.slimframework.com/docs/start/installation.html) +- [Support Forum](http://help.slimframework.com) +- [Twitter](https://twitter.com/slimphp) +- [Resources](https://github.com/xssc/awesome-slim) + +## Security + +If you discover security related issues, please email security@slimframework.com instead of using the issue tracker. + +## Credits + +- [Josh Lockhart](https://github.com/codeguy) +- [Andrew Smith](https://github.com/silentworks) +- [Rob Allen](https://github.com/akrabat) +- [Gabriel Manricks](https://github.com/gmanricks) +- [All Contributors](../../contributors) + +## License + +The Slim Framework is licensed under the MIT license. See [License File](LICENSE.md) for more information. diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/App.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/App.php new file mode 100644 index 000000000000..96d82cb81fb4 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/App.php @@ -0,0 +1,644 @@ +container = $container; + } + + /** + * Enable access to the DI container by consumers of $app + * + * @return ContainerInterface + */ + public function getContainer() + { + return $this->container; + } + + /** + * Add middleware + * + * This method prepends new middleware to the app's middleware stack. + * + * @param callable|string $callable The callback routine + * + * @return static + */ + public function add($callable) + { + return $this->addMiddleware(new DeferredCallable($callable, $this->container)); + } + + /** + * Calling a non-existant method on App checks to see if there's an item + * in the container that is callable and if so, calls it. + * + * @param string $method + * @param array $args + * @return mixed + */ + public function __call($method, $args) + { + if ($this->container->has($method)) { + $obj = $this->container->get($method); + if (is_callable($obj)) { + return call_user_func_array($obj, $args); + } + } + + throw new \BadMethodCallException("Method $method is not a valid method"); + } + + /******************************************************************************** + * Router proxy methods + *******************************************************************************/ + + /** + * Add GET route + * + * @param string $pattern The route URI pattern + * @param callable|string $callable The route callback routine + * + * @return \Slim\Interfaces\RouteInterface + */ + public function get($pattern, $callable) + { + return $this->map(['GET'], $pattern, $callable); + } + + /** + * Add POST route + * + * @param string $pattern The route URI pattern + * @param callable|string $callable The route callback routine + * + * @return \Slim\Interfaces\RouteInterface + */ + public function post($pattern, $callable) + { + return $this->map(['POST'], $pattern, $callable); + } + + /** + * Add PUT route + * + * @param string $pattern The route URI pattern + * @param callable|string $callable The route callback routine + * + * @return \Slim\Interfaces\RouteInterface + */ + public function put($pattern, $callable) + { + return $this->map(['PUT'], $pattern, $callable); + } + + /** + * Add PATCH route + * + * @param string $pattern The route URI pattern + * @param callable|string $callable The route callback routine + * + * @return \Slim\Interfaces\RouteInterface + */ + public function patch($pattern, $callable) + { + return $this->map(['PATCH'], $pattern, $callable); + } + + /** + * Add DELETE route + * + * @param string $pattern The route URI pattern + * @param callable|string $callable The route callback routine + * + * @return \Slim\Interfaces\RouteInterface + */ + public function delete($pattern, $callable) + { + return $this->map(['DELETE'], $pattern, $callable); + } + + /** + * Add OPTIONS route + * + * @param string $pattern The route URI pattern + * @param callable|string $callable The route callback routine + * + * @return \Slim\Interfaces\RouteInterface + */ + public function options($pattern, $callable) + { + return $this->map(['OPTIONS'], $pattern, $callable); + } + + /** + * Add route for any HTTP method + * + * @param string $pattern The route URI pattern + * @param callable|string $callable The route callback routine + * + * @return \Slim\Interfaces\RouteInterface + */ + public function any($pattern, $callable) + { + return $this->map(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], $pattern, $callable); + } + + /** + * Add route with multiple methods + * + * @param string[] $methods Numeric array of HTTP method names + * @param string $pattern The route URI pattern + * @param callable|string $callable The route callback routine + * + * @return RouteInterface + */ + public function map(array $methods, $pattern, $callable) + { + if ($callable instanceof Closure) { + $callable = $callable->bindTo($this->container); + } + + $route = $this->container->get('router')->map($methods, $pattern, $callable); + if (is_callable([$route, 'setContainer'])) { + $route->setContainer($this->container); + } + + if (is_callable([$route, 'setOutputBuffering'])) { + $route->setOutputBuffering($this->container->get('settings')['outputBuffering']); + } + + return $route; + } + + /** + * Route Groups + * + * This method accepts a route pattern and a callback. All route + * declarations in the callback will be prepended by the group(s) + * that it is in. + * + * @param string $pattern + * @param callable $callable + * + * @return RouteGroupInterface + */ + public function group($pattern, $callable) + { + /** @var RouteGroup $group */ + $group = $this->container->get('router')->pushGroup($pattern, $callable); + $group->setContainer($this->container); + $group($this); + $this->container->get('router')->popGroup(); + return $group; + } + + /******************************************************************************** + * Runner + *******************************************************************************/ + + /** + * Run application + * + * This method traverses the application middleware stack and then sends the + * resultant Response object to the HTTP client. + * + * @param bool|false $silent + * @return ResponseInterface + * + * @throws Exception + * @throws MethodNotAllowedException + * @throws NotFoundException + */ + public function run($silent = false) + { + $request = $this->container->get('request'); + $response = $this->container->get('response'); + + $response = $this->process($request, $response); + + if (!$silent) { + $this->respond($response); + } + + return $response; + } + + /** + * Process a request + * + * This method traverses the application middleware stack and then returns the + * resultant Response object. + * + * @param ServerRequestInterface $request + * @param ResponseInterface $response + * @return ResponseInterface + * + * @throws Exception + * @throws MethodNotAllowedException + * @throws NotFoundException + */ + public function process(ServerRequestInterface $request, ResponseInterface $response) + { + // Ensure basePath is set + $router = $this->container->get('router'); + if (is_callable([$request->getUri(), 'getBasePath']) && is_callable([$router, 'setBasePath'])) { + $router->setBasePath($request->getUri()->getBasePath()); + } + + // Dispatch the Router first if the setting for this is on + if ($this->container->get('settings')['determineRouteBeforeAppMiddleware'] === true) { + // Dispatch router (note: you won't be able to alter routes after this) + $request = $this->dispatchRouterAndPrepareRoute($request, $router); + } + + // Traverse middleware stack + try { + $response = $this->callMiddlewareStack($request, $response); + } catch (Exception $e) { + $response = $this->handleException($e, $request, $response); + } catch (Throwable $e) { + $response = $this->handlePhpError($e, $request, $response); + } + + $response = $this->finalize($response); + + return $response; + } + + /** + * Send the response the client + * + * @param ResponseInterface $response + */ + public function respond(ResponseInterface $response) + { + // Send response + if (!headers_sent()) { + // Status + header(sprintf( + 'HTTP/%s %s %s', + $response->getProtocolVersion(), + $response->getStatusCode(), + $response->getReasonPhrase() + )); + + // Headers + foreach ($response->getHeaders() as $name => $values) { + foreach ($values as $value) { + header(sprintf('%s: %s', $name, $value), false); + } + } + } + + // Body + if (!$this->isEmptyResponse($response)) { + $body = $response->getBody(); + if ($body->isSeekable()) { + $body->rewind(); + } + $settings = $this->container->get('settings'); + $chunkSize = $settings['responseChunkSize']; + + $contentLength = $response->getHeaderLine('Content-Length'); + if (!$contentLength) { + $contentLength = $body->getSize(); + } + + + if (isset($contentLength)) { + $amountToRead = $contentLength; + while ($amountToRead > 0 && !$body->eof()) { + $data = $body->read(min($chunkSize, $amountToRead)); + echo $data; + + $amountToRead -= strlen($data); + + if (connection_status() != CONNECTION_NORMAL) { + break; + } + } + } else { + while (!$body->eof()) { + echo $body->read($chunkSize); + if (connection_status() != CONNECTION_NORMAL) { + break; + } + } + } + } + } + + /** + * Invoke application + * + * This method implements the middleware interface. It receives + * Request and Response objects, and it returns a Response object + * after compiling the routes registered in the Router and dispatching + * the Request object to the appropriate Route callback routine. + * + * @param ServerRequestInterface $request The most recent Request object + * @param ResponseInterface $response The most recent Response object + * + * @return ResponseInterface + * @throws MethodNotAllowedException + * @throws NotFoundException + */ + public function __invoke(ServerRequestInterface $request, ResponseInterface $response) + { + // Get the route info + $routeInfo = $request->getAttribute('routeInfo'); + + /** @var \Slim\Interfaces\RouterInterface $router */ + $router = $this->container->get('router'); + + // If router hasn't been dispatched or the URI changed then dispatch + if (null === $routeInfo || ($routeInfo['request'] !== [$request->getMethod(), (string) $request->getUri()])) { + $request = $this->dispatchRouterAndPrepareRoute($request, $router); + $routeInfo = $request->getAttribute('routeInfo'); + } + + if ($routeInfo[0] === Dispatcher::FOUND) { + $route = $router->lookupRoute($routeInfo[1]); + return $route->run($request, $response); + } elseif ($routeInfo[0] === Dispatcher::METHOD_NOT_ALLOWED) { + if (!$this->container->has('notAllowedHandler')) { + throw new MethodNotAllowedException($request, $response, $routeInfo[1]); + } + /** @var callable $notAllowedHandler */ + $notAllowedHandler = $this->container->get('notAllowedHandler'); + return $notAllowedHandler($request, $response, $routeInfo[1]); + } + + if (!$this->container->has('notFoundHandler')) { + throw new NotFoundException($request, $response); + } + /** @var callable $notFoundHandler */ + $notFoundHandler = $this->container->get('notFoundHandler'); + return $notFoundHandler($request, $response); + } + + /** + * Perform a sub-request from within an application route + * + * This method allows you to prepare and initiate a sub-request, run within + * the context of the current request. This WILL NOT issue a remote HTTP + * request. Instead, it will route the provided URL, method, headers, + * cookies, body, and server variables against the set of registered + * application routes. The result response object is returned. + * + * @param string $method The request method (e.g., GET, POST, PUT, etc.) + * @param string $path The request URI path + * @param string $query The request URI query string + * @param array $headers The request headers (key-value array) + * @param array $cookies The request cookies (key-value array) + * @param string $bodyContent The request body + * @param ResponseInterface $response The response object (optional) + * @return ResponseInterface + */ + public function subRequest( + $method, + $path, + $query = '', + array $headers = [], + array $cookies = [], + $bodyContent = '', + ResponseInterface $response = null + ) { + $env = $this->container->get('environment'); + $uri = Uri::createFromEnvironment($env)->withPath($path)->withQuery($query); + $headers = new Headers($headers); + $serverParams = $env->all(); + $body = new Body(fopen('php://temp', 'r+')); + $body->write($bodyContent); + $body->rewind(); + $request = new Request($method, $uri, $headers, $cookies, $serverParams, $body); + + if (!$response) { + $response = $this->container->get('response'); + } + + return $this($request, $response); + } + + /** + * Dispatch the router to find the route. Prepare the route for use. + * + * @param ServerRequestInterface $request + * @param RouterInterface $router + * @return ServerRequestInterface + */ + protected function dispatchRouterAndPrepareRoute(ServerRequestInterface $request, RouterInterface $router) + { + $routeInfo = $router->dispatch($request); + + if ($routeInfo[0] === Dispatcher::FOUND) { + $routeArguments = []; + foreach ($routeInfo[2] as $k => $v) { + $routeArguments[$k] = urldecode($v); + } + + $route = $router->lookupRoute($routeInfo[1]); + $route->prepare($request, $routeArguments); + + // add route to the request's attributes in case a middleware or handler needs access to the route + $request = $request->withAttribute('route', $route); + } + + $routeInfo['request'] = [$request->getMethod(), (string) $request->getUri()]; + + return $request->withAttribute('routeInfo', $routeInfo); + } + + /** + * Finalize response + * + * @param ResponseInterface $response + * @return ResponseInterface + */ + protected function finalize(ResponseInterface $response) + { + // stop PHP sending a Content-Type automatically + ini_set('default_mimetype', ''); + + if ($this->isEmptyResponse($response)) { + return $response->withoutHeader('Content-Type')->withoutHeader('Content-Length'); + } + + // Add Content-Length header if `addContentLengthHeader` setting is set + if (isset($this->container->get('settings')['addContentLengthHeader']) && + $this->container->get('settings')['addContentLengthHeader'] == true) { + if (ob_get_length() > 0) { + throw new \RuntimeException("Unexpected data in output buffer. " . + "Maybe you have characters before an opening getBody()->getSize(); + if ($size !== null && !$response->hasHeader('Content-Length')) { + $response = $response->withHeader('Content-Length', (string) $size); + } + } + + return $response; + } + + /** + * Helper method, which returns true if the provided response must not output a body and false + * if the response could have a body. + * + * @see https://tools.ietf.org/html/rfc7231 + * + * @param ResponseInterface $response + * @return bool + */ + protected function isEmptyResponse(ResponseInterface $response) + { + if (method_exists($response, 'isEmpty')) { + return $response->isEmpty(); + } + + return in_array($response->getStatusCode(), [204, 205, 304]); + } + + /** + * Call relevant handler from the Container if needed. If it doesn't exist, + * then just re-throw. + * + * @param Exception $e + * @param ServerRequestInterface $request + * @param ResponseInterface $response + * + * @return ResponseInterface + * @throws Exception if a handler is needed and not found + */ + protected function handleException(Exception $e, ServerRequestInterface $request, ResponseInterface $response) + { + if ($e instanceof MethodNotAllowedException) { + $handler = 'notAllowedHandler'; + $params = [$e->getRequest(), $e->getResponse(), $e->getAllowedMethods()]; + } elseif ($e instanceof NotFoundException) { + $handler = 'notFoundHandler'; + $params = [$e->getRequest(), $e->getResponse()]; + } elseif ($e instanceof SlimException) { + // This is a Stop exception and contains the response + return $e->getResponse(); + } else { + // Other exception, use $request and $response params + $handler = 'errorHandler'; + $params = [$request, $response, $e]; + } + + if ($this->container->has($handler)) { + $callable = $this->container->get($handler); + // Call the registered handler + return call_user_func_array($callable, $params); + } + + // No handlers found, so just throw the exception + throw $e; + } + + /** + * Call relevant handler from the Container if needed. If it doesn't exist, + * then just re-throw. + * + * @param Throwable $e + * @param ServerRequestInterface $request + * @param ResponseInterface $response + * @return ResponseInterface + * @throws Throwable + */ + protected function handlePhpError(Throwable $e, ServerRequestInterface $request, ResponseInterface $response) + { + $handler = 'phpErrorHandler'; + $params = [$request, $response, $e]; + + if ($this->container->has($handler)) { + $callable = $this->container->get($handler); + // Call the registered handler + return call_user_func_array($callable, $params); + } + + // No handlers found, so just throw the exception + throw $e; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/CallableResolver.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/CallableResolver.php new file mode 100644 index 000000000000..705a9f207fe0 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/CallableResolver.php @@ -0,0 +1,87 @@ +container = $container; + } + + /** + * Resolve toResolve into a closure that that the router can dispatch. + * + * If toResolve is of the format 'class:method', then try to extract 'class' + * from the container otherwise instantiate it and then dispatch 'method'. + * + * @param mixed $toResolve + * + * @return callable + * + * @throws RuntimeException if the callable does not exist + * @throws RuntimeException if the callable is not resolvable + */ + public function resolve($toResolve) + { + $resolved = $toResolve; + + if (!is_callable($toResolve) && is_string($toResolve)) { + // check for slim callable as "class:method" + $callablePattern = '!^([^\:]+)\:([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)$!'; + if (preg_match($callablePattern, $toResolve, $matches)) { + $class = $matches[1]; + $method = $matches[2]; + + if ($this->container->has($class)) { + $resolved = [$this->container->get($class), $method]; + } else { + if (!class_exists($class)) { + throw new RuntimeException(sprintf('Callable %s does not exist', $class)); + } + $resolved = [new $class($this->container), $method]; + } + } else { + // check if string is something in the DIC that's callable or is a class name which + // has an __invoke() method + $class = $toResolve; + if ($this->container->has($class)) { + $resolved = $this->container->get($class); + } else { + if (!class_exists($class)) { + throw new RuntimeException(sprintf('Callable %s does not exist', $class)); + } + $resolved = new $class($this->container); + } + } + } + + if (!is_callable($resolved)) { + throw new RuntimeException(sprintf('%s is not resolvable', $toResolve)); + } + + return $resolved; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/CallableResolverAwareTrait.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/CallableResolverAwareTrait.php new file mode 100644 index 000000000000..f7ff485282d2 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/CallableResolverAwareTrait.php @@ -0,0 +1,47 @@ +container instanceof ContainerInterface) { + return $callable; + } + + /** @var CallableResolverInterface $resolver */ + $resolver = $this->container->get('callableResolver'); + + return $resolver->resolve($callable); + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Collection.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Collection.php new file mode 100644 index 000000000000..d33acd9ce32d --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Collection.php @@ -0,0 +1,204 @@ + $value) { + $this->set($key, $value); + } + } + + /******************************************************************************** + * Collection interface + *******************************************************************************/ + + /** + * Set collection item + * + * @param string $key The data key + * @param mixed $value The data value + */ + public function set($key, $value) + { + $this->data[$key] = $value; + } + + /** + * Get collection item for key + * + * @param string $key The data key + * @param mixed $default The default value to return if data key does not exist + * + * @return mixed The key's value, or the default value + */ + public function get($key, $default = null) + { + return $this->has($key) ? $this->data[$key] : $default; + } + + /** + * Add item to collection + * + * @param array $items Key-value array of data to append to this collection + */ + public function replace(array $items) + { + foreach ($items as $key => $value) { + $this->set($key, $value); + } + } + + /** + * Get all items in collection + * + * @return array The collection's source data + */ + public function all() + { + return $this->data; + } + + /** + * Get collection keys + * + * @return array The collection's source data keys + */ + public function keys() + { + return array_keys($this->data); + } + + /** + * Does this collection have a given key? + * + * @param string $key The data key + * + * @return bool + */ + public function has($key) + { + return array_key_exists($key, $this->data); + } + + /** + * Remove item from collection + * + * @param string $key The data key + */ + public function remove($key) + { + unset($this->data[$key]); + } + + /** + * Remove all items from collection + */ + public function clear() + { + $this->data = []; + } + + /******************************************************************************** + * ArrayAccess interface + *******************************************************************************/ + + /** + * Does this collection have a given key? + * + * @param string $key The data key + * + * @return bool + */ + public function offsetExists($key) + { + return $this->has($key); + } + + /** + * Get collection item for key + * + * @param string $key The data key + * + * @return mixed The key's value, or the default value + */ + public function offsetGet($key) + { + return $this->get($key); + } + + /** + * Set collection item + * + * @param string $key The data key + * @param mixed $value The data value + */ + public function offsetSet($key, $value) + { + $this->set($key, $value); + } + + /** + * Remove item from collection + * + * @param string $key The data key + */ + public function offsetUnset($key) + { + $this->remove($key); + } + + /** + * Get number of items in collection + * + * @return int + */ + public function count() + { + return count($this->data); + } + + /******************************************************************************** + * IteratorAggregate interface + *******************************************************************************/ + + /** + * Get collection iterator + * + * @return \ArrayIterator + */ + public function getIterator() + { + return new ArrayIterator($this->data); + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Container.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Container.php new file mode 100644 index 000000000000..c97f2b3fdf44 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Container.php @@ -0,0 +1,181 @@ + '1.1', + 'responseChunkSize' => 4096, + 'outputBuffering' => 'append', + 'determineRouteBeforeAppMiddleware' => false, + 'displayErrorDetails' => false, + 'addContentLengthHeader' => true, + 'routerCacheFile' => false, + ]; + + /** + * Create new container + * + * @param array $values The parameters or objects. + */ + public function __construct(array $values = []) + { + parent::__construct($values); + + $userSettings = isset($values['settings']) ? $values['settings'] : []; + $this->registerDefaultServices($userSettings); + } + + /** + * This function registers the default services that Slim needs to work. + * + * All services are shared - that is, they are registered such that the + * same instance is returned on subsequent calls. + * + * @param array $userSettings Associative array of application settings + * + * @return void + */ + private function registerDefaultServices($userSettings) + { + $defaultSettings = $this->defaultSettings; + + /** + * This service MUST return an array or an + * instance of \ArrayAccess. + * + * @return array|\ArrayAccess + */ + $this['settings'] = function () use ($userSettings, $defaultSettings) { + return new Collection(array_merge($defaultSettings, $userSettings)); + }; + + $defaultProvider = new DefaultServicesProvider(); + $defaultProvider->register($this); + } + + /******************************************************************************** + * Methods to satisfy Interop\Container\ContainerInterface + *******************************************************************************/ + + /** + * Finds an entry of the container by its identifier and returns it. + * + * @param string $id Identifier of the entry to look for. + * + * @throws ContainerValueNotFoundException No entry was found for this identifier. + * @throws ContainerException Error while retrieving the entry. + * + * @return mixed Entry. + */ + public function get($id) + { + if (!$this->offsetExists($id)) { + throw new ContainerValueNotFoundException(sprintf('Identifier "%s" is not defined.', $id)); + } + try { + return $this->offsetGet($id); + } catch (\InvalidArgumentException $exception) { + if ($this->exceptionThrownByContainer($exception)) { + throw new SlimContainerException( + sprintf('Container error while retrieving "%s"', $id), + null, + $exception + ); + } else { + throw $exception; + } + } + } + + /** + * Tests whether an exception needs to be recast for compliance with Container-Interop. This will be if the + * exception was thrown by Pimple. + * + * @param \InvalidArgumentException $exception + * + * @return bool + */ + private function exceptionThrownByContainer(\InvalidArgumentException $exception) + { + $trace = $exception->getTrace()[0]; + + return $trace['class'] === PimpleContainer::class && $trace['function'] === 'offsetGet'; + } + + /** + * Returns true if the container can return an entry for the given identifier. + * Returns false otherwise. + * + * @param string $id Identifier of the entry to look for. + * + * @return boolean + */ + public function has($id) + { + return $this->offsetExists($id); + } + + + /******************************************************************************** + * Magic methods for convenience + *******************************************************************************/ + + public function __get($name) + { + return $this->get($name); + } + + public function __isset($name) + { + return $this->has($name); + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/DefaultServicesProvider.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/DefaultServicesProvider.php new file mode 100644 index 000000000000..c18d8757204d --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/DefaultServicesProvider.php @@ -0,0 +1,204 @@ +get('environment')); + }; + } + + if (!isset($container['response'])) { + /** + * PSR-7 Response object + * + * @param Container $container + * + * @return ResponseInterface + */ + $container['response'] = function ($container) { + $headers = new Headers(['Content-Type' => 'text/html; charset=UTF-8']); + $response = new Response(200, $headers); + + return $response->withProtocolVersion($container->get('settings')['httpVersion']); + }; + } + + if (!isset($container['router'])) { + /** + * This service MUST return a SHARED instance + * of \Slim\Interfaces\RouterInterface. + * + * @param Container $container + * + * @return RouterInterface + */ + $container['router'] = function ($container) { + $routerCacheFile = false; + if (isset($container->get('settings')['routerCacheFile'])) { + $routerCacheFile = $container->get('settings')['routerCacheFile']; + } + + return (new Router)->setCacheFile($routerCacheFile); + }; + } + + if (!isset($container['foundHandler'])) { + /** + * This service MUST return a SHARED instance + * of \Slim\Interfaces\InvocationStrategyInterface. + * + * @return InvocationStrategyInterface + */ + $container['foundHandler'] = function () { + return new RequestResponse; + }; + } + + if (!isset($container['phpErrorHandler'])) { + /** + * This service MUST return a callable + * that accepts three arguments: + * + * 1. Instance of \Psr\Http\Message\ServerRequestInterface + * 2. Instance of \Psr\Http\Message\ResponseInterface + * 3. Instance of \Error + * + * The callable MUST return an instance of + * \Psr\Http\Message\ResponseInterface. + * + * @param Container $container + * + * @return callable + */ + $container['phpErrorHandler'] = function ($container) { + return new PhpError($container->get('settings')['displayErrorDetails']); + }; + } + + if (!isset($container['errorHandler'])) { + /** + * This service MUST return a callable + * that accepts three arguments: + * + * 1. Instance of \Psr\Http\Message\ServerRequestInterface + * 2. Instance of \Psr\Http\Message\ResponseInterface + * 3. Instance of \Exception + * + * The callable MUST return an instance of + * \Psr\Http\Message\ResponseInterface. + * + * @param Container $container + * + * @return callable + */ + $container['errorHandler'] = function ($container) { + return new Error($container->get('settings')['displayErrorDetails']); + }; + } + + if (!isset($container['notFoundHandler'])) { + /** + * This service MUST return a callable + * that accepts two arguments: + * + * 1. Instance of \Psr\Http\Message\ServerRequestInterface + * 2. Instance of \Psr\Http\Message\ResponseInterface + * + * The callable MUST return an instance of + * \Psr\Http\Message\ResponseInterface. + * + * @return callable + */ + $container['notFoundHandler'] = function () { + return new NotFound; + }; + } + + if (!isset($container['notAllowedHandler'])) { + /** + * This service MUST return a callable + * that accepts three arguments: + * + * 1. Instance of \Psr\Http\Message\ServerRequestInterface + * 2. Instance of \Psr\Http\Message\ResponseInterface + * 3. Array of allowed HTTP methods + * + * The callable MUST return an instance of + * \Psr\Http\Message\ResponseInterface. + * + * @return callable + */ + $container['notAllowedHandler'] = function () { + return new NotAllowed; + }; + } + + if (!isset($container['callableResolver'])) { + /** + * Instance of \Slim\Interfaces\CallableResolverInterface + * + * @param Container $container + * + * @return CallableResolverInterface + */ + $container['callableResolver'] = function ($container) { + return new CallableResolver($container); + }; + } + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/DeferredCallable.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/DeferredCallable.php new file mode 100644 index 000000000000..def58ab23b36 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/DeferredCallable.php @@ -0,0 +1,39 @@ +callable = $callable; + $this->container = $container; + } + + public function __invoke() + { + $callable = $this->resolveCallable($this->callable); + if ($callable instanceof Closure) { + $callable = $callable->bindTo($this->container); + } + + $args = func_get_args(); + + return call_user_func_array($callable, $args); + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Exception/ContainerException.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Exception/ContainerException.php new file mode 100644 index 000000000000..0200e1a8611d --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Exception/ContainerException.php @@ -0,0 +1,20 @@ +allowedMethods = $allowedMethods; + } + + /** + * Get allowed methods + * + * @return string[] + */ + public function getAllowedMethods() + { + return $this->allowedMethods; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Exception/NotFoundException.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Exception/NotFoundException.php new file mode 100644 index 000000000000..65365eb99d6c --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Exception/NotFoundException.php @@ -0,0 +1,14 @@ +request = $request; + $this->response = $response; + } + + /** + * Get request + * + * @return ServerRequestInterface + */ + public function getRequest() + { + return $this->request; + } + + /** + * Get response + * + * @return ResponseInterface + */ + public function getResponse() + { + return $this->response; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/AbstractError.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/AbstractError.php new file mode 100644 index 000000000000..5a6cee30a941 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/AbstractError.php @@ -0,0 +1,99 @@ +displayErrorDetails = (bool) $displayErrorDetails; + } + + /** + * Write to the error log if displayErrorDetails is false + * + * @param \Exception|\Throwable $throwable + * + * @return void + */ + protected function writeToErrorLog($throwable) + { + if ($this->displayErrorDetails) { + return; + } + + $message = 'Slim Application Error:' . PHP_EOL; + $message .= $this->renderThrowableAsText($throwable); + while ($throwable = $throwable->getPrevious()) { + $message .= PHP_EOL . 'Previous error:' . PHP_EOL; + $message .= $this->renderThrowableAsText($throwable); + } + + $message .= PHP_EOL . 'View in rendered output by enabling the "displayErrorDetails" setting.' . PHP_EOL; + + $this->logError($message); + } + + /** + * Render error as Text. + * + * @param \Exception|\Throwable $throwable + * + * @return string + */ + protected function renderThrowableAsText($throwable) + { + $text = sprintf('Type: %s' . PHP_EOL, get_class($throwable)); + + if ($code = $throwable->getCode()) { + $text .= sprintf('Code: %s' . PHP_EOL, $code); + } + + if ($message = $throwable->getMessage()) { + $text .= sprintf('Message: %s' . PHP_EOL, htmlentities($message)); + } + + if ($file = $throwable->getFile()) { + $text .= sprintf('File: %s' . PHP_EOL, $file); + } + + if ($line = $throwable->getLine()) { + $text .= sprintf('Line: %s' . PHP_EOL, $line); + } + + if ($trace = $throwable->getTraceAsString()) { + $text .= sprintf('Trace: %s', $trace); + } + + return $text; + } + + /** + * Wraps the error_log function so that this can be easily tested + * + * @param $message + */ + protected function logError($message) + { + error_log($message); + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/AbstractHandler.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/AbstractHandler.php new file mode 100644 index 000000000000..decdf725ce89 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/AbstractHandler.php @@ -0,0 +1,59 @@ +getHeaderLine('Accept'); + $selectedContentTypes = array_intersect(explode(',', $acceptHeader), $this->knownContentTypes); + + if (count($selectedContentTypes)) { + return current($selectedContentTypes); + } + + // handle +json and +xml specially + if (preg_match('/\+(json|xml)/', $acceptHeader, $matches)) { + $mediaType = 'application/' . $matches[1]; + if (in_array($mediaType, $this->knownContentTypes)) { + return $mediaType; + } + } + + return 'text/html'; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/Error.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/Error.php new file mode 100644 index 000000000000..b9951888efb8 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/Error.php @@ -0,0 +1,206 @@ +determineContentType($request); + switch ($contentType) { + case 'application/json': + $output = $this->renderJsonErrorMessage($exception); + break; + + case 'text/xml': + case 'application/xml': + $output = $this->renderXmlErrorMessage($exception); + break; + + case 'text/html': + $output = $this->renderHtmlErrorMessage($exception); + break; + + default: + throw new UnexpectedValueException('Cannot render unknown content type ' . $contentType); + } + + $this->writeToErrorLog($exception); + + $body = new Body(fopen('php://temp', 'r+')); + $body->write($output); + + return $response + ->withStatus(500) + ->withHeader('Content-type', $contentType) + ->withBody($body); + } + + /** + * Render HTML error page + * + * @param \Exception $exception + * + * @return string + */ + protected function renderHtmlErrorMessage(\Exception $exception) + { + $title = 'Slim Application Error'; + + if ($this->displayErrorDetails) { + $html = '

The application could not run because of the following error:

'; + $html .= '

Details

'; + $html .= $this->renderHtmlException($exception); + + while ($exception = $exception->getPrevious()) { + $html .= '

Previous exception

'; + $html .= $this->renderHtmlException($exception); + } + } else { + $html = '

A website error has occurred. Sorry for the temporary inconvenience.

'; + } + + $output = sprintf( + "" . + "%s

%s

%s", + $title, + $title, + $html + ); + + return $output; + } + + /** + * Render exception as HTML. + * + * @param \Exception $exception + * + * @return string + */ + protected function renderHtmlException(\Exception $exception) + { + $html = sprintf('
Type: %s
', get_class($exception)); + + if (($code = $exception->getCode())) { + $html .= sprintf('
Code: %s
', $code); + } + + if (($message = $exception->getMessage())) { + $html .= sprintf('
Message: %s
', htmlentities($message)); + } + + if (($file = $exception->getFile())) { + $html .= sprintf('
File: %s
', $file); + } + + if (($line = $exception->getLine())) { + $html .= sprintf('
Line: %s
', $line); + } + + if (($trace = $exception->getTraceAsString())) { + $html .= '

Trace

'; + $html .= sprintf('
%s
', htmlentities($trace)); + } + + return $html; + } + + /** + * Render JSON error + * + * @param \Exception $exception + * + * @return string + */ + protected function renderJsonErrorMessage(\Exception $exception) + { + $error = [ + 'message' => 'Slim Application Error', + ]; + + if ($this->displayErrorDetails) { + $error['exception'] = []; + + do { + $error['exception'][] = [ + 'type' => get_class($exception), + 'code' => $exception->getCode(), + 'message' => $exception->getMessage(), + 'file' => $exception->getFile(), + 'line' => $exception->getLine(), + 'trace' => explode("\n", $exception->getTraceAsString()), + ]; + } while ($exception = $exception->getPrevious()); + } + + return json_encode($error, JSON_PRETTY_PRINT); + } + + /** + * Render XML error + * + * @param \Exception $exception + * + * @return string + */ + protected function renderXmlErrorMessage(\Exception $exception) + { + $xml = "\n Slim Application Error\n"; + if ($this->displayErrorDetails) { + do { + $xml .= " \n"; + $xml .= " " . get_class($exception) . "\n"; + $xml .= " " . $exception->getCode() . "\n"; + $xml .= " " . $this->createCdataSection($exception->getMessage()) . "\n"; + $xml .= " " . $exception->getFile() . "\n"; + $xml .= " " . $exception->getLine() . "\n"; + $xml .= " " . $this->createCdataSection($exception->getTraceAsString()) . "\n"; + $xml .= " \n"; + } while ($exception = $exception->getPrevious()); + } + $xml .= ""; + + return $xml; + } + + /** + * Returns a CDATA section with the given content. + * + * @param string $content + * @return string + */ + private function createCdataSection($content) + { + return sprintf('', str_replace(']]>', ']]]]>', $content)); + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/NotAllowed.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/NotAllowed.php new file mode 100644 index 000000000000..3442f20bc528 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/NotAllowed.php @@ -0,0 +1,147 @@ +getMethod() === 'OPTIONS') { + $status = 200; + $contentType = 'text/plain'; + $output = $this->renderPlainNotAllowedMessage($methods); + } else { + $status = 405; + $contentType = $this->determineContentType($request); + switch ($contentType) { + case 'application/json': + $output = $this->renderJsonNotAllowedMessage($methods); + break; + + case 'text/xml': + case 'application/xml': + $output = $this->renderXmlNotAllowedMessage($methods); + break; + + case 'text/html': + $output = $this->renderHtmlNotAllowedMessage($methods); + break; + default: + throw new UnexpectedValueException('Cannot render unknown content type ' . $contentType); + } + } + + $body = new Body(fopen('php://temp', 'r+')); + $body->write($output); + $allow = implode(', ', $methods); + + return $response + ->withStatus($status) + ->withHeader('Content-type', $contentType) + ->withHeader('Allow', $allow) + ->withBody($body); + } + + /** + * Render PLAIN not allowed message + * + * @param array $methods + * @return string + */ + protected function renderPlainNotAllowedMessage($methods) + { + $allow = implode(', ', $methods); + + return 'Allowed methods: ' . $allow; + } + + /** + * Render JSON not allowed message + * + * @param array $methods + * @return string + */ + protected function renderJsonNotAllowedMessage($methods) + { + $allow = implode(', ', $methods); + + return '{"message":"Method not allowed. Must be one of: ' . $allow . '"}'; + } + + /** + * Render XML not allowed message + * + * @param array $methods + * @return string + */ + protected function renderXmlNotAllowedMessage($methods) + { + $allow = implode(', ', $methods); + + return "Method not allowed. Must be one of: $allow"; + } + + /** + * Render HTML not allowed message + * + * @param array $methods + * @return string + */ + protected function renderHtmlNotAllowedMessage($methods) + { + $allow = implode(', ', $methods); + $output = << + + Method not allowed + + + +

Method not allowed

+

Method not allowed. Must be one of: $allow

+ + +END; + + return $output; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/NotFound.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/NotFound.php new file mode 100644 index 000000000000..ab1d47a4575d --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/NotFound.php @@ -0,0 +1,126 @@ +determineContentType($request); + switch ($contentType) { + case 'application/json': + $output = $this->renderJsonNotFoundOutput(); + break; + + case 'text/xml': + case 'application/xml': + $output = $this->renderXmlNotFoundOutput(); + break; + + case 'text/html': + $output = $this->renderHtmlNotFoundOutput($request); + break; + + default: + throw new UnexpectedValueException('Cannot render unknown content type ' . $contentType); + } + + $body = new Body(fopen('php://temp', 'r+')); + $body->write($output); + + return $response->withStatus(404) + ->withHeader('Content-Type', $contentType) + ->withBody($body); + } + + /** + * Return a response for application/json content not found + * + * @return ResponseInterface + */ + protected function renderJsonNotFoundOutput() + { + return '{"message":"Not found"}'; + } + + /** + * Return a response for xml content not found + * + * @return ResponseInterface + */ + protected function renderXmlNotFoundOutput() + { + return 'Not found'; + } + + /** + * Return a response for text/html content not found + * + * @param ServerRequestInterface $request The most recent Request object + * + * @return ResponseInterface + */ + protected function renderHtmlNotFoundOutput(ServerRequestInterface $request) + { + $homeUrl = (string)($request->getUri()->withPath('')->withQuery('')->withFragment('')); + return << + + Page Not Found + + + +

Page Not Found

+

+ The page you are looking for could not be found. Check the address bar + to ensure your URL is spelled correctly. If all else fails, you can + visit our home page at the link below. +

+
Visit the Home Page + + +END; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/PhpError.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/PhpError.php new file mode 100644 index 000000000000..0122ddb07852 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/PhpError.php @@ -0,0 +1,205 @@ +determineContentType($request); + switch ($contentType) { + case 'application/json': + $output = $this->renderJsonErrorMessage($error); + break; + + case 'text/xml': + case 'application/xml': + $output = $this->renderXmlErrorMessage($error); + break; + + case 'text/html': + $output = $this->renderHtmlErrorMessage($error); + break; + default: + throw new UnexpectedValueException('Cannot render unknown content type ' . $contentType); + } + + $this->writeToErrorLog($error); + + $body = new Body(fopen('php://temp', 'r+')); + $body->write($output); + + return $response + ->withStatus(500) + ->withHeader('Content-type', $contentType) + ->withBody($body); + } + + /** + * Render HTML error page + * + * @param \Throwable $error + * + * @return string + */ + protected function renderHtmlErrorMessage(\Throwable $error) + { + $title = 'Slim Application Error'; + + if ($this->displayErrorDetails) { + $html = '

The application could not run because of the following error:

'; + $html .= '

Details

'; + $html .= $this->renderHtmlError($error); + + while ($error = $error->getPrevious()) { + $html .= '

Previous error

'; + $html .= $this->renderHtmlError($error); + } + } else { + $html = '

A website error has occurred. Sorry for the temporary inconvenience.

'; + } + + $output = sprintf( + "" . + "%s

%s

%s", + $title, + $title, + $html + ); + + return $output; + } + + /** + * Render error as HTML. + * + * @param \Throwable $error + * + * @return string + */ + protected function renderHtmlError(\Throwable $error) + { + $html = sprintf('
Type: %s
', get_class($error)); + + if (($code = $error->getCode())) { + $html .= sprintf('
Code: %s
', $code); + } + + if (($message = $error->getMessage())) { + $html .= sprintf('
Message: %s
', htmlentities($message)); + } + + if (($file = $error->getFile())) { + $html .= sprintf('
File: %s
', $file); + } + + if (($line = $error->getLine())) { + $html .= sprintf('
Line: %s
', $line); + } + + if (($trace = $error->getTraceAsString())) { + $html .= '

Trace

'; + $html .= sprintf('
%s
', htmlentities($trace)); + } + + return $html; + } + + /** + * Render JSON error + * + * @param \Throwable $error + * + * @return string + */ + protected function renderJsonErrorMessage(\Throwable $error) + { + $json = [ + 'message' => 'Slim Application Error', + ]; + + if ($this->displayErrorDetails) { + $json['error'] = []; + + do { + $json['error'][] = [ + 'type' => get_class($error), + 'code' => $error->getCode(), + 'message' => $error->getMessage(), + 'file' => $error->getFile(), + 'line' => $error->getLine(), + 'trace' => explode("\n", $error->getTraceAsString()), + ]; + } while ($error = $error->getPrevious()); + } + + return json_encode($json, JSON_PRETTY_PRINT); + } + + /** + * Render XML error + * + * @param \Throwable $error + * + * @return string + */ + protected function renderXmlErrorMessage(\Throwable $error) + { + $xml = "\n Slim Application Error\n"; + if ($this->displayErrorDetails) { + do { + $xml .= " \n"; + $xml .= " " . get_class($error) . "\n"; + $xml .= " " . $error->getCode() . "\n"; + $xml .= " " . $this->createCdataSection($error->getMessage()) . "\n"; + $xml .= " " . $error->getFile() . "\n"; + $xml .= " " . $error->getLine() . "\n"; + $xml .= " " . $this->createCdataSection($error->getTraceAsString()) . "\n"; + $xml .= " \n"; + } while ($error = $error->getPrevious()); + } + $xml .= ""; + + return $xml; + } + + /** + * Returns a CDATA section with the given content. + * + * @param string $content + * @return string + */ + private function createCdataSection($content) + { + return sprintf('', str_replace(']]>', ']]]]>', $content)); + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php new file mode 100644 index 000000000000..157bdebee947 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php @@ -0,0 +1,43 @@ + $v) { + $request = $request->withAttribute($k, $v); + } + + return call_user_func($callable, $request, $response, $routeArguments); + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php new file mode 100644 index 000000000000..11793d36e403 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php @@ -0,0 +1,42 @@ + '', + 'domain' => null, + 'hostonly' => null, + 'path' => null, + 'expires' => null, + 'secure' => false, + 'httponly' => false + ]; + + /** + * Create new cookies helper + * + * @param array $cookies + */ + public function __construct(array $cookies = []) + { + $this->requestCookies = $cookies; + } + + /** + * Set default cookie properties + * + * @param array $settings + */ + public function setDefaults(array $settings) + { + $this->defaults = array_replace($this->defaults, $settings); + } + + /** + * Get request cookie + * + * @param string $name Cookie name + * @param mixed $default Cookie default value + * + * @return mixed Cookie value if present, else default + */ + public function get($name, $default = null) + { + return isset($this->requestCookies[$name]) ? $this->requestCookies[$name] : $default; + } + + /** + * Set response cookie + * + * @param string $name Cookie name + * @param string|array $value Cookie value, or cookie properties + */ + public function set($name, $value) + { + if (!is_array($value)) { + $value = ['value' => (string)$value]; + } + $this->responseCookies[$name] = array_replace($this->defaults, $value); + } + + /** + * Convert to `Set-Cookie` headers + * + * @return string[] + */ + public function toHeaders() + { + $headers = []; + foreach ($this->responseCookies as $name => $properties) { + $headers[] = $this->toHeader($name, $properties); + } + + return $headers; + } + + /** + * Convert to `Set-Cookie` header + * + * @param string $name Cookie name + * @param array $properties Cookie properties + * + * @return string + */ + protected function toHeader($name, array $properties) + { + $result = urlencode($name) . '=' . urlencode($properties['value']); + + if (isset($properties['domain'])) { + $result .= '; domain=' . $properties['domain']; + } + + if (isset($properties['path'])) { + $result .= '; path=' . $properties['path']; + } + + if (isset($properties['expires'])) { + if (is_string($properties['expires'])) { + $timestamp = strtotime($properties['expires']); + } else { + $timestamp = (int)$properties['expires']; + } + if ($timestamp !== 0) { + $result .= '; expires=' . gmdate('D, d-M-Y H:i:s e', $timestamp); + } + } + + if (isset($properties['secure']) && $properties['secure']) { + $result .= '; secure'; + } + + if (isset($properties['hostonly']) && $properties['hostonly']) { + $result .= '; HostOnly'; + } + + if (isset($properties['httponly']) && $properties['httponly']) { + $result .= '; HttpOnly'; + } + + return $result; + } + + /** + * Parse HTTP request `Cookie:` header and extract + * into a PHP associative array. + * + * @param string $header The raw HTTP request `Cookie:` header + * + * @return array Associative array of cookie names and values + * + * @throws InvalidArgumentException if the cookie data cannot be parsed + */ + public static function parseHeader($header) + { + if (is_array($header) === true) { + $header = isset($header[0]) ? $header[0] : ''; + } + + if (is_string($header) === false) { + throw new InvalidArgumentException('Cannot parse Cookie data. Header value must be a string.'); + } + + $header = rtrim($header, "\r\n"); + $pieces = preg_split('@\s*[;,]\s*@', $header); + $cookies = []; + + foreach ($pieces as $cookie) { + $cookie = explode('=', $cookie, 2); + + if (count($cookie) === 2) { + $key = urldecode($cookie[0]); + $value = urldecode($cookie[1]); + + if (!isset($cookies[$key])) { + $cookies[$key] = $value; + } + } + } + + return $cookies; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Environment.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Environment.php new file mode 100644 index 000000000000..a106fa8b8770 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Environment.php @@ -0,0 +1,52 @@ + 'HTTP/1.1', + 'REQUEST_METHOD' => 'GET', + 'SCRIPT_NAME' => '', + 'REQUEST_URI' => '', + 'QUERY_STRING' => '', + 'SERVER_NAME' => 'localhost', + 'SERVER_PORT' => 80, + 'HTTP_HOST' => 'localhost', + 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'HTTP_ACCEPT_LANGUAGE' => 'en-US,en;q=0.8', + 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.3', + 'HTTP_USER_AGENT' => 'Slim Framework', + 'REMOTE_ADDR' => '127.0.0.1', + 'REQUEST_TIME' => time(), + 'REQUEST_TIME_FLOAT' => microtime(true), + ], $userData); + + return new static($data); + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Headers.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Headers.php new file mode 100644 index 000000000000..4aa7a5e4de01 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Headers.php @@ -0,0 +1,222 @@ + 1, + 'CONTENT_LENGTH' => 1, + 'PHP_AUTH_USER' => 1, + 'PHP_AUTH_PW' => 1, + 'PHP_AUTH_DIGEST' => 1, + 'AUTH_TYPE' => 1, + ]; + + /** + * Create new headers collection with data extracted from + * the application Environment object + * + * @param Environment $environment The Slim application Environment + * + * @return self + */ + public static function createFromEnvironment(Environment $environment) + { + $data = []; + $environment = self::determineAuthorization($environment); + foreach ($environment as $key => $value) { + $key = strtoupper($key); + if (isset(static::$special[$key]) || strpos($key, 'HTTP_') === 0) { + if ($key !== 'HTTP_CONTENT_LENGTH') { + $data[$key] = $value; + } + } + } + + return new static($data); + } + + /** + * If HTTP_AUTHORIZATION does not exist tries to get it from + * getallheaders() when available. + * + * @param Environment $environment The Slim application Environment + * + * @return Environment + */ + + public static function determineAuthorization(Environment $environment) + { + $authorization = $environment->get('HTTP_AUTHORIZATION'); + + if (null === $authorization && is_callable('getallheaders')) { + $headers = getallheaders(); + $headers = array_change_key_case($headers, CASE_LOWER); + if (isset($headers['authorization'])) { + $environment->set('HTTP_AUTHORIZATION', $headers['authorization']); + } + } + + return $environment; + } + + /** + * Return array of HTTP header names and values. + * This method returns the _original_ header name + * as specified by the end user. + * + * @return array + */ + public function all() + { + $all = parent::all(); + $out = []; + foreach ($all as $key => $props) { + $out[$props['originalKey']] = $props['value']; + } + + return $out; + } + + /** + * Set HTTP header value + * + * This method sets a header value. It replaces + * any values that may already exist for the header name. + * + * @param string $key The case-insensitive header name + * @param string $value The header value + */ + public function set($key, $value) + { + if (!is_array($value)) { + $value = [$value]; + } + parent::set($this->normalizeKey($key), [ + 'value' => $value, + 'originalKey' => $key + ]); + } + + /** + * Get HTTP header value + * + * @param string $key The case-insensitive header name + * @param mixed $default The default value if key does not exist + * + * @return string[] + */ + public function get($key, $default = null) + { + if ($this->has($key)) { + return parent::get($this->normalizeKey($key))['value']; + } + + return $default; + } + + /** + * Get HTTP header key as originally specified + * + * @param string $key The case-insensitive header name + * @param mixed $default The default value if key does not exist + * + * @return string + */ + public function getOriginalKey($key, $default = null) + { + if ($this->has($key)) { + return parent::get($this->normalizeKey($key))['originalKey']; + } + + return $default; + } + + /** + * Add HTTP header value + * + * This method appends a header value. Unlike the set() method, + * this method _appends_ this new value to any values + * that already exist for this header name. + * + * @param string $key The case-insensitive header name + * @param array|string $value The new header value(s) + */ + public function add($key, $value) + { + $oldValues = $this->get($key, []); + $newValues = is_array($value) ? $value : [$value]; + $this->set($key, array_merge($oldValues, array_values($newValues))); + } + + /** + * Does this collection have a given header? + * + * @param string $key The case-insensitive header name + * + * @return bool + */ + public function has($key) + { + return parent::has($this->normalizeKey($key)); + } + + /** + * Remove header from collection + * + * @param string $key The case-insensitive header name + */ + public function remove($key) + { + parent::remove($this->normalizeKey($key)); + } + + /** + * Normalize header name + * + * This method transforms header names into a + * normalized form. This is how we enable case-insensitive + * header names in the other methods in this class. + * + * @param string $key The case-insensitive header name + * + * @return string Normalized header name + */ + public function normalizeKey($key) + { + $key = strtr(strtolower($key), '_', '-'); + if (strpos($key, 'http-') === 0) { + $key = substr($key, 5); + } + + return $key; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Message.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Message.php new file mode 100644 index 000000000000..d0e832d695f1 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Message.php @@ -0,0 +1,295 @@ +protocolVersion; + } + + /** + * Return an instance with the specified HTTP protocol version. + * + * The version string MUST contain only the HTTP version number (e.g., + * "1.1", "1.0"). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new protocol version. + * + * @param string $version HTTP protocol version + * @return static + * @throws InvalidArgumentException if the http version is an invalid number + */ + public function withProtocolVersion($version) + { + static $valid = [ + '1.0' => true, + '1.1' => true, + '2.0' => true, + ]; + if (!isset($valid[$version])) { + throw new InvalidArgumentException('Invalid HTTP version. Must be one of: 1.0, 1.1, 2.0'); + } + $clone = clone $this; + $clone->protocolVersion = $version; + + return $clone; + } + + /******************************************************************************* + * Headers + ******************************************************************************/ + + /** + * Retrieves all message header values. + * + * The keys represent the header name as it will be sent over the wire, and + * each value is an array of strings associated with the header. + * + * // Represent the headers as a string + * foreach ($message->getHeaders() as $name => $values) { + * echo $name . ": " . implode(", ", $values); + * } + * + * // Emit headers iteratively: + * foreach ($message->getHeaders() as $name => $values) { + * foreach ($values as $value) { + * header(sprintf('%s: %s', $name, $value), false); + * } + * } + * + * While header names are not case-sensitive, getHeaders() will preserve the + * exact case in which headers were originally specified. + * + * @return array Returns an associative array of the message's headers. Each + * key MUST be a header name, and each value MUST be an array of strings + * for that header. + */ + public function getHeaders() + { + return $this->headers->all(); + } + + /** + * Checks if a header exists by the given case-insensitive name. + * + * @param string $name Case-insensitive header field name. + * @return bool Returns true if any header names match the given header + * name using a case-insensitive string comparison. Returns false if + * no matching header name is found in the message. + */ + public function hasHeader($name) + { + return $this->headers->has($name); + } + + /** + * Retrieves a message header value by the given case-insensitive name. + * + * This method returns an array of all the header values of the given + * case-insensitive header name. + * + * If the header does not appear in the message, this method MUST return an + * empty array. + * + * @param string $name Case-insensitive header field name. + * @return string[] An array of string values as provided for the given + * header. If the header does not appear in the message, this method MUST + * return an empty array. + */ + public function getHeader($name) + { + return $this->headers->get($name, []); + } + + /** + * Retrieves a comma-separated string of the values for a single header. + * + * This method returns all of the header values of the given + * case-insensitive header name as a string concatenated together using + * a comma. + * + * NOTE: Not all header values may be appropriately represented using + * comma concatenation. For such headers, use getHeader() instead + * and supply your own delimiter when concatenating. + * + * If the header does not appear in the message, this method MUST return + * an empty string. + * + * @param string $name Case-insensitive header field name. + * @return string A string of values as provided for the given header + * concatenated together using a comma. If the header does not appear in + * the message, this method MUST return an empty string. + */ + public function getHeaderLine($name) + { + return implode(',', $this->headers->get($name, [])); + } + + /** + * Return an instance with the provided value replacing the specified header. + * + * While header names are case-insensitive, the casing of the header will + * be preserved by this function, and returned from getHeaders(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new and/or updated header and value. + * + * @param string $name Case-insensitive header field name. + * @param string|string[] $value Header value(s). + * @return static + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withHeader($name, $value) + { + $clone = clone $this; + $clone->headers->set($name, $value); + + return $clone; + } + + /** + * Return an instance with the specified header appended with the given value. + * + * Existing values for the specified header will be maintained. The new + * value(s) will be appended to the existing list. If the header did not + * exist previously, it will be added. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new header and/or value. + * + * @param string $name Case-insensitive header field name to add. + * @param string|string[] $value Header value(s). + * @return static + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withAddedHeader($name, $value) + { + $clone = clone $this; + $clone->headers->add($name, $value); + + return $clone; + } + + /** + * Return an instance without the specified header. + * + * Header resolution MUST be done without case-sensitivity. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the named header. + * + * @param string $name Case-insensitive header field name to remove. + * @return static + */ + public function withoutHeader($name) + { + $clone = clone $this; + $clone->headers->remove($name); + + return $clone; + } + + /******************************************************************************* + * Body + ******************************************************************************/ + + /** + * Gets the body of the message. + * + * @return StreamInterface Returns the body as a stream. + */ + public function getBody() + { + return $this->body; + } + + /** + * Return an instance with the specified message body. + * + * The body MUST be a StreamInterface object. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return a new instance that has the + * new body stream. + * + * @param StreamInterface $body Body. + * @return static + * @throws \InvalidArgumentException When the body is not valid. + */ + public function withBody(StreamInterface $body) + { + // TODO: Test for invalid body? + $clone = clone $this; + $clone->body = $body; + + return $clone; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Request.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Request.php new file mode 100644 index 000000000000..7d5b185dcd83 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Request.php @@ -0,0 +1,1156 @@ + 1, + 'DELETE' => 1, + 'GET' => 1, + 'HEAD' => 1, + 'OPTIONS' => 1, + 'PATCH' => 1, + 'POST' => 1, + 'PUT' => 1, + 'TRACE' => 1, + ]; + + /** + * Create new HTTP request with data extracted from the application + * Environment object + * + * @param Environment $environment The Slim application Environment + * + * @return self + */ + public static function createFromEnvironment(Environment $environment) + { + $method = $environment['REQUEST_METHOD']; + $uri = Uri::createFromEnvironment($environment); + $headers = Headers::createFromEnvironment($environment); + $cookies = Cookies::parseHeader($headers->get('Cookie', [])); + $serverParams = $environment->all(); + $body = new RequestBody(); + $uploadedFiles = UploadedFile::createFromEnvironment($environment); + + $request = new static($method, $uri, $headers, $cookies, $serverParams, $body, $uploadedFiles); + + if ($method === 'POST' && + in_array($request->getMediaType(), ['application/x-www-form-urlencoded', 'multipart/form-data']) + ) { + // parsed body must be $_POST + $request = $request->withParsedBody($_POST); + } + return $request; + } + + /** + * Create new HTTP request. + * + * Adds a host header when none was provided and a host is defined in uri. + * + * @param string $method The request method + * @param UriInterface $uri The request URI object + * @param HeadersInterface $headers The request headers collection + * @param array $cookies The request cookies collection + * @param array $serverParams The server environment variables + * @param StreamInterface $body The request body object + * @param array $uploadedFiles The request uploadedFiles collection + */ + public function __construct( + $method, + UriInterface $uri, + HeadersInterface $headers, + array $cookies, + array $serverParams, + StreamInterface $body, + array $uploadedFiles = [] + ) { + $this->originalMethod = $this->filterMethod($method); + $this->uri = $uri; + $this->headers = $headers; + $this->cookies = $cookies; + $this->serverParams = $serverParams; + $this->attributes = new Collection(); + $this->body = $body; + $this->uploadedFiles = $uploadedFiles; + + if (isset($serverParams['SERVER_PROTOCOL'])) { + $this->protocolVersion = str_replace('HTTP/', '', $serverParams['SERVER_PROTOCOL']); + } + + if (!$this->headers->has('Host') || $this->uri->getHost() !== '') { + $this->headers->set('Host', $this->uri->getHost()); + } + + $this->registerMediaTypeParser('application/json', function ($input) { + return json_decode($input, true); + }); + + $this->registerMediaTypeParser('application/xml', function ($input) { + $backup = libxml_disable_entity_loader(true); + $result = simplexml_load_string($input); + libxml_disable_entity_loader($backup); + return $result; + }); + + $this->registerMediaTypeParser('text/xml', function ($input) { + $backup = libxml_disable_entity_loader(true); + $result = simplexml_load_string($input); + libxml_disable_entity_loader($backup); + return $result; + }); + + $this->registerMediaTypeParser('application/x-www-form-urlencoded', function ($input) { + parse_str($input, $data); + return $data; + }); + } + + /** + * This method is applied to the cloned object + * after PHP performs an initial shallow-copy. This + * method completes a deep-copy by creating new objects + * for the cloned object's internal reference pointers. + */ + public function __clone() + { + $this->headers = clone $this->headers; + $this->attributes = clone $this->attributes; + $this->body = clone $this->body; + } + + /******************************************************************************* + * Method + ******************************************************************************/ + + /** + * Retrieves the HTTP method of the request. + * + * @return string Returns the request method. + */ + public function getMethod() + { + if ($this->method === null) { + $this->method = $this->originalMethod; + $customMethod = $this->getHeaderLine('X-Http-Method-Override'); + + if ($customMethod) { + $this->method = $this->filterMethod($customMethod); + } elseif ($this->originalMethod === 'POST') { + $body = $this->getParsedBody(); + + if (is_object($body) && property_exists($body, '_METHOD')) { + $this->method = $this->filterMethod((string)$body->_METHOD); + } elseif (is_array($body) && isset($body['_METHOD'])) { + $this->method = $this->filterMethod((string)$body['_METHOD']); + } + + if ($this->getBody()->eof()) { + $this->getBody()->rewind(); + } + } + } + + return $this->method; + } + + /** + * Get the original HTTP method (ignore override). + * + * Note: This method is not part of the PSR-7 standard. + * + * @return string + */ + public function getOriginalMethod() + { + return $this->originalMethod; + } + + /** + * Return an instance with the provided HTTP method. + * + * While HTTP method names are typically all uppercase characters, HTTP + * method names are case-sensitive and thus implementations SHOULD NOT + * modify the given string. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * changed request method. + * + * @param string $method Case-sensitive method. + * @return self + * @throws \InvalidArgumentException for invalid HTTP methods. + */ + public function withMethod($method) + { + $method = $this->filterMethod($method); + $clone = clone $this; + $clone->originalMethod = $method; + $clone->method = $method; + + return $clone; + } + + /** + * Validate the HTTP method + * + * @param null|string $method + * @return null|string + * @throws \InvalidArgumentException on invalid HTTP method. + */ + protected function filterMethod($method) + { + if ($method === null) { + return $method; + } + + if (!is_string($method)) { + throw new InvalidArgumentException(sprintf( + 'Unsupported HTTP method; must be a string, received %s', + (is_object($method) ? get_class($method) : gettype($method)) + )); + } + + $method = strtoupper($method); + if (!isset($this->validMethods[$method])) { + throw new InvalidArgumentException(sprintf( + 'Unsupported HTTP method "%s" provided', + $method + )); + } + + return $method; + } + + /** + * Does this request use a given method? + * + * Note: This method is not part of the PSR-7 standard. + * + * @param string $method HTTP method + * @return bool + */ + public function isMethod($method) + { + return $this->getMethod() === $method; + } + + /** + * Is this a GET request? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isGet() + { + return $this->isMethod('GET'); + } + + /** + * Is this a POST request? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isPost() + { + return $this->isMethod('POST'); + } + + /** + * Is this a PUT request? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isPut() + { + return $this->isMethod('PUT'); + } + + /** + * Is this a PATCH request? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isPatch() + { + return $this->isMethod('PATCH'); + } + + /** + * Is this a DELETE request? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isDelete() + { + return $this->isMethod('DELETE'); + } + + /** + * Is this a HEAD request? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isHead() + { + return $this->isMethod('HEAD'); + } + + /** + * Is this a OPTIONS request? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isOptions() + { + return $this->isMethod('OPTIONS'); + } + + /** + * Is this an XHR request? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isXhr() + { + return $this->getHeaderLine('X-Requested-With') === 'XMLHttpRequest'; + } + + /******************************************************************************* + * URI + ******************************************************************************/ + + /** + * Retrieves the message's request target. + * + * Retrieves the message's request-target either as it will appear (for + * clients), as it appeared at request (for servers), or as it was + * specified for the instance (see withRequestTarget()). + * + * In most cases, this will be the origin-form of the composed URI, + * unless a value was provided to the concrete implementation (see + * withRequestTarget() below). + * + * If no URI is available, and no request-target has been specifically + * provided, this method MUST return the string "/". + * + * @return string + */ + public function getRequestTarget() + { + if ($this->requestTarget) { + return $this->requestTarget; + } + + if ($this->uri === null) { + return '/'; + } + + $basePath = $this->uri->getBasePath(); + $path = $this->uri->getPath(); + $path = $basePath . '/' . ltrim($path, '/'); + + $query = $this->uri->getQuery(); + if ($query) { + $path .= '?' . $query; + } + $this->requestTarget = $path; + + return $this->requestTarget; + } + + /** + * Return an instance with the specific request-target. + * + * If the request needs a non-origin-form request-target — e.g., for + * specifying an absolute-form, authority-form, or asterisk-form — + * this method may be used to create an instance with the specified + * request-target, verbatim. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * changed request target. + * + * @link http://tools.ietf.org/html/rfc7230#section-2.7 (for the various + * request-target forms allowed in request messages) + * @param mixed $requestTarget + * @return self + * @throws InvalidArgumentException if the request target is invalid + */ + public function withRequestTarget($requestTarget) + { + if (preg_match('#\s#', $requestTarget)) { + throw new InvalidArgumentException( + 'Invalid request target provided; must be a string and cannot contain whitespace' + ); + } + $clone = clone $this; + $clone->requestTarget = $requestTarget; + + return $clone; + } + + /** + * Retrieves the URI instance. + * + * This method MUST return a UriInterface instance. + * + * @link http://tools.ietf.org/html/rfc3986#section-4.3 + * @return UriInterface Returns a UriInterface instance + * representing the URI of the request. + */ + public function getUri() + { + return $this->uri; + } + + /** + * Returns an instance with the provided URI. + * + * This method MUST update the Host header of the returned request by + * default if the URI contains a host component. If the URI does not + * contain a host component, any pre-existing Host header MUST be carried + * over to the returned request. + * + * You can opt-in to preserving the original state of the Host header by + * setting `$preserveHost` to `true`. When `$preserveHost` is set to + * `true`, this method interacts with the Host header in the following ways: + * + * - If the the Host header is missing or empty, and the new URI contains + * a host component, this method MUST update the Host header in the returned + * request. + * - If the Host header is missing or empty, and the new URI does not contain a + * host component, this method MUST NOT update the Host header in the returned + * request. + * - If a Host header is present and non-empty, this method MUST NOT update + * the Host header in the returned request. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new UriInterface instance. + * + * @link http://tools.ietf.org/html/rfc3986#section-4.3 + * @param UriInterface $uri New request URI to use. + * @param bool $preserveHost Preserve the original state of the Host header. + * @return self + */ + public function withUri(UriInterface $uri, $preserveHost = false) + { + $clone = clone $this; + $clone->uri = $uri; + + if (!$preserveHost) { + if ($uri->getHost() !== '') { + $clone->headers->set('Host', $uri->getHost()); + } + } else { + if ($this->uri->getHost() !== '' && (!$this->hasHeader('Host') || $this->getHeader('Host') === null)) { + $clone->headers->set('Host', $uri->getHost()); + } + } + + return $clone; + } + + /** + * Get request content type. + * + * Note: This method is not part of the PSR-7 standard. + * + * @return string|null The request content type, if known + */ + public function getContentType() + { + $result = $this->getHeader('Content-Type'); + + return $result ? $result[0] : null; + } + + /** + * Get request media type, if known. + * + * Note: This method is not part of the PSR-7 standard. + * + * @return string|null The request media type, minus content-type params + */ + public function getMediaType() + { + $contentType = $this->getContentType(); + if ($contentType) { + $contentTypeParts = preg_split('/\s*[;,]\s*/', $contentType); + + return strtolower($contentTypeParts[0]); + } + + return null; + } + + /** + * Get request media type params, if known. + * + * Note: This method is not part of the PSR-7 standard. + * + * @return array + */ + public function getMediaTypeParams() + { + $contentType = $this->getContentType(); + $contentTypeParams = []; + if ($contentType) { + $contentTypeParts = preg_split('/\s*[;,]\s*/', $contentType); + $contentTypePartsLength = count($contentTypeParts); + for ($i = 1; $i < $contentTypePartsLength; $i++) { + $paramParts = explode('=', $contentTypeParts[$i]); + $contentTypeParams[strtolower($paramParts[0])] = $paramParts[1]; + } + } + + return $contentTypeParams; + } + + /** + * Get request content character set, if known. + * + * Note: This method is not part of the PSR-7 standard. + * + * @return string|null + */ + public function getContentCharset() + { + $mediaTypeParams = $this->getMediaTypeParams(); + if (isset($mediaTypeParams['charset'])) { + return $mediaTypeParams['charset']; + } + + return null; + } + + /** + * Get request content length, if known. + * + * Note: This method is not part of the PSR-7 standard. + * + * @return int|null + */ + public function getContentLength() + { + $result = $this->headers->get('Content-Length'); + + return $result ? (int)$result[0] : null; + } + + /******************************************************************************* + * Cookies + ******************************************************************************/ + + /** + * Retrieve cookies. + * + * Retrieves cookies sent by the client to the server. + * + * The data MUST be compatible with the structure of the $_COOKIE + * superglobal. + * + * @return array + */ + public function getCookieParams() + { + return $this->cookies; + } + + /** + * Return an instance with the specified cookies. + * + * The data IS NOT REQUIRED to come from the $_COOKIE superglobal, but MUST + * be compatible with the structure of $_COOKIE. Typically, this data will + * be injected at instantiation. + * + * This method MUST NOT update the related Cookie header of the request + * instance, nor related values in the server params. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated cookie values. + * + * @param array $cookies Array of key/value pairs representing cookies. + * @return self + */ + public function withCookieParams(array $cookies) + { + $clone = clone $this; + $clone->cookies = $cookies; + + return $clone; + } + + /******************************************************************************* + * Query Params + ******************************************************************************/ + + /** + * Retrieve query string arguments. + * + * Retrieves the deserialized query string arguments, if any. + * + * Note: the query params might not be in sync with the URI or server + * params. If you need to ensure you are only getting the original + * values, you may need to parse the query string from `getUri()->getQuery()` + * or from the `QUERY_STRING` server param. + * + * @return array + */ + public function getQueryParams() + { + if (is_array($this->queryParams)) { + return $this->queryParams; + } + + if ($this->uri === null) { + return []; + } + + parse_str($this->uri->getQuery(), $this->queryParams); // <-- URL decodes data + + return $this->queryParams; + } + + /** + * Return an instance with the specified query string arguments. + * + * These values SHOULD remain immutable over the course of the incoming + * request. They MAY be injected during instantiation, such as from PHP's + * $_GET superglobal, or MAY be derived from some other value such as the + * URI. In cases where the arguments are parsed from the URI, the data + * MUST be compatible with what PHP's parse_str() would return for + * purposes of how duplicate query parameters are handled, and how nested + * sets are handled. + * + * Setting query string arguments MUST NOT change the URI stored by the + * request, nor the values in the server params. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated query string arguments. + * + * @param array $query Array of query string arguments, typically from + * $_GET. + * @return self + */ + public function withQueryParams(array $query) + { + $clone = clone $this; + $clone->queryParams = $query; + + return $clone; + } + + /******************************************************************************* + * File Params + ******************************************************************************/ + + /** + * Retrieve normalized file upload data. + * + * This method returns upload metadata in a normalized tree, with each leaf + * an instance of Psr\Http\Message\UploadedFileInterface. + * + * These values MAY be prepared from $_FILES or the message body during + * instantiation, or MAY be injected via withUploadedFiles(). + * + * @return array An array tree of UploadedFileInterface instances; an empty + * array MUST be returned if no data is present. + */ + public function getUploadedFiles() + { + return $this->uploadedFiles; + } + + /** + * Create a new instance with the specified uploaded files. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param array $uploadedFiles An array tree of UploadedFileInterface instances. + * @return self + * @throws \InvalidArgumentException if an invalid structure is provided. + */ + public function withUploadedFiles(array $uploadedFiles) + { + $clone = clone $this; + $clone->uploadedFiles = $uploadedFiles; + + return $clone; + } + + /******************************************************************************* + * Server Params + ******************************************************************************/ + + /** + * Retrieve server parameters. + * + * Retrieves data related to the incoming request environment, + * typically derived from PHP's $_SERVER superglobal. The data IS NOT + * REQUIRED to originate from $_SERVER. + * + * @return array + */ + public function getServerParams() + { + return $this->serverParams; + } + + /******************************************************************************* + * Attributes + ******************************************************************************/ + + /** + * Retrieve attributes derived from the request. + * + * The request "attributes" may be used to allow injection of any + * parameters derived from the request: e.g., the results of path + * match operations; the results of decrypting cookies; the results of + * deserializing non-form-encoded message bodies; etc. Attributes + * will be application and request specific, and CAN be mutable. + * + * @return array Attributes derived from the request. + */ + public function getAttributes() + { + return $this->attributes->all(); + } + + /** + * Retrieve a single derived request attribute. + * + * Retrieves a single derived request attribute as described in + * getAttributes(). If the attribute has not been previously set, returns + * the default value as provided. + * + * This method obviates the need for a hasAttribute() method, as it allows + * specifying a default value to return if the attribute is not found. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $default Default value to return if the attribute does not exist. + * @return mixed + */ + public function getAttribute($name, $default = null) + { + return $this->attributes->get($name, $default); + } + + /** + * Return an instance with the specified derived request attribute. + * + * This method allows setting a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $value The value of the attribute. + * @return self + */ + public function withAttribute($name, $value) + { + $clone = clone $this; + $clone->attributes->set($name, $value); + + return $clone; + } + + /** + * Create a new instance with the specified derived request attributes. + * + * Note: This method is not part of the PSR-7 standard. + * + * This method allows setting all new derived request attributes as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return a new instance that has the + * updated attributes. + * + * @param array $attributes New attributes + * @return self + */ + public function withAttributes(array $attributes) + { + $clone = clone $this; + $clone->attributes = new Collection($attributes); + + return $clone; + } + + /** + * Return an instance that removes the specified derived request attribute. + * + * This method allows removing a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @return self + */ + public function withoutAttribute($name) + { + $clone = clone $this; + $clone->attributes->remove($name); + + return $clone; + } + + /******************************************************************************* + * Body + ******************************************************************************/ + + /** + * Retrieve any parameters provided in the request body. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, this method MUST + * return the contents of $_POST. + * + * Otherwise, this method may return any results of deserializing + * the request body content; as parsing returns structured content, the + * potential types MUST be arrays or objects only. A null value indicates + * the absence of body content. + * + * @return null|array|object The deserialized body parameters, if any. + * These will typically be an array or object. + * @throws RuntimeException if the request body media type parser returns an invalid value + */ + public function getParsedBody() + { + if ($this->bodyParsed !== false) { + return $this->bodyParsed; + } + + if (!$this->body) { + return null; + } + + $mediaType = $this->getMediaType(); + + // look for a media type with a structured syntax suffix (RFC 6839) + $parts = explode('+', $mediaType); + if (count($parts) >= 2) { + $mediaType = 'application/' . $parts[count($parts)-1]; + } + + if (isset($this->bodyParsers[$mediaType]) === true) { + $body = (string)$this->getBody(); + $parsed = $this->bodyParsers[$mediaType]($body); + + if (!is_null($parsed) && !is_object($parsed) && !is_array($parsed)) { + throw new RuntimeException( + 'Request body media type parser return value must be an array, an object, or null' + ); + } + $this->bodyParsed = $parsed; + return $this->bodyParsed; + } + + return null; + } + + /** + * Return an instance with the specified body parameters. + * + * These MAY be injected during instantiation. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, use this method + * ONLY to inject the contents of $_POST. + * + * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of + * deserializing the request body content. Deserialization/parsing returns + * structured data, and, as such, this method ONLY accepts arrays or objects, + * or a null value if nothing was available to parse. + * + * As an example, if content negotiation determines that the request data + * is a JSON payload, this method could be used to create a request + * instance with the deserialized parameters. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param null|array|object $data The deserialized body data. This will + * typically be in an array or object. + * @return self + * @throws \InvalidArgumentException if an unsupported argument type is + * provided. + */ + public function withParsedBody($data) + { + if (!is_null($data) && !is_object($data) && !is_array($data)) { + throw new InvalidArgumentException('Parsed body value must be an array, an object, or null'); + } + + $clone = clone $this; + $clone->bodyParsed = $data; + + return $clone; + } + + /** + * Force Body to be parsed again. + * + * Note: This method is not part of the PSR-7 standard. + * + * @return self + */ + public function reparseBody() + { + $this->bodyParsed = false; + + return $this; + } + + /** + * Register media type parser. + * + * Note: This method is not part of the PSR-7 standard. + * + * @param string $mediaType A HTTP media type (excluding content-type + * params). + * @param callable $callable A callable that returns parsed contents for + * media type. + */ + public function registerMediaTypeParser($mediaType, callable $callable) + { + if ($callable instanceof Closure) { + $callable = $callable->bindTo($this); + } + $this->bodyParsers[(string)$mediaType] = $callable; + } + + /******************************************************************************* + * Parameters (e.g., POST and GET data) + ******************************************************************************/ + + /** + * Fetch request parameter value from body or query string (in that order). + * + * Note: This method is not part of the PSR-7 standard. + * + * @param string $key The parameter key. + * @param string $default The default value. + * + * @return mixed The parameter value. + */ + public function getParam($key, $default = null) + { + $postParams = $this->getParsedBody(); + $getParams = $this->getQueryParams(); + $result = $default; + if (is_array($postParams) && isset($postParams[$key])) { + $result = $postParams[$key]; + } elseif (is_object($postParams) && property_exists($postParams, $key)) { + $result = $postParams->$key; + } elseif (isset($getParams[$key])) { + $result = $getParams[$key]; + } + + return $result; + } + + /** + * Fetch parameter value from request body. + * + * Note: This method is not part of the PSR-7 standard. + * + * @param $key + * @param null $default + * + * @return null + */ + public function getParsedBodyParam($key, $default = null) + { + $postParams = $this->getParsedBody(); + $result = $default; + if (is_array($postParams) && isset($postParams[$key])) { + $result = $postParams[$key]; + } elseif (is_object($postParams) && property_exists($postParams, $key)) { + $result = $postParams->$key; + } + + return $result; + } + + /** + * Fetch parameter value from query string. + * + * Note: This method is not part of the PSR-7 standard. + * + * @param $key + * @param null $default + * + * @return null + */ + public function getQueryParam($key, $default = null) + { + $getParams = $this->getQueryParams(); + $result = $default; + if (isset($getParams[$key])) { + $result = $getParams[$key]; + } + + return $result; + } + + /** + * Fetch assocative array of body and query string parameters. + * + * Note: This method is not part of the PSR-7 standard. + * + * @return array + */ + public function getParams() + { + $params = $this->getQueryParams(); + $postParams = $this->getParsedBody(); + if ($postParams) { + $params = array_merge($params, (array)$postParams); + } + + return $params; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/RequestBody.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/RequestBody.php new file mode 100644 index 000000000000..2345fe4354c7 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/RequestBody.php @@ -0,0 +1,27 @@ + 'Continue', + 101 => 'Switching Protocols', + 102 => 'Processing', + //Successful 2xx + 200 => 'OK', + 201 => 'Created', + 202 => 'Accepted', + 203 => 'Non-Authoritative Information', + 204 => 'No Content', + 205 => 'Reset Content', + 206 => 'Partial Content', + 207 => 'Multi-Status', + 208 => 'Already Reported', + 226 => 'IM Used', + //Redirection 3xx + 300 => 'Multiple Choices', + 301 => 'Moved Permanently', + 302 => 'Found', + 303 => 'See Other', + 304 => 'Not Modified', + 305 => 'Use Proxy', + 306 => '(Unused)', + 307 => 'Temporary Redirect', + 308 => 'Permanent Redirect', + //Client Error 4xx + 400 => 'Bad Request', + 401 => 'Unauthorized', + 402 => 'Payment Required', + 403 => 'Forbidden', + 404 => 'Not Found', + 405 => 'Method Not Allowed', + 406 => 'Not Acceptable', + 407 => 'Proxy Authentication Required', + 408 => 'Request Timeout', + 409 => 'Conflict', + 410 => 'Gone', + 411 => 'Length Required', + 412 => 'Precondition Failed', + 413 => 'Request Entity Too Large', + 414 => 'Request-URI Too Long', + 415 => 'Unsupported Media Type', + 416 => 'Requested Range Not Satisfiable', + 417 => 'Expectation Failed', + 418 => 'I\'m a teapot', + 422 => 'Unprocessable Entity', + 423 => 'Locked', + 424 => 'Failed Dependency', + 426 => 'Upgrade Required', + 428 => 'Precondition Required', + 429 => 'Too Many Requests', + 431 => 'Request Header Fields Too Large', + 451 => 'Unavailable For Legal Reasons', + //Server Error 5xx + 500 => 'Internal Server Error', + 501 => 'Not Implemented', + 502 => 'Bad Gateway', + 503 => 'Service Unavailable', + 504 => 'Gateway Timeout', + 505 => 'HTTP Version Not Supported', + 506 => 'Variant Also Negotiates', + 507 => 'Insufficient Storage', + 508 => 'Loop Detected', + 510 => 'Not Extended', + 511 => 'Network Authentication Required', + ]; + + /** + * Create new HTTP response. + * + * @param int $status The response status code. + * @param HeadersInterface|null $headers The response headers. + * @param StreamInterface|null $body The response body. + */ + public function __construct($status = 200, HeadersInterface $headers = null, StreamInterface $body = null) + { + $this->status = $this->filterStatus($status); + $this->headers = $headers ? $headers : new Headers(); + $this->body = $body ? $body : new Body(fopen('php://temp', 'r+')); + } + + /** + * This method is applied to the cloned object + * after PHP performs an initial shallow-copy. This + * method completes a deep-copy by creating new objects + * for the cloned object's internal reference pointers. + */ + public function __clone() + { + $this->headers = clone $this->headers; + } + + /******************************************************************************* + * Status + ******************************************************************************/ + + /** + * Gets the response status code. + * + * The status code is a 3-digit integer result code of the server's attempt + * to understand and satisfy the request. + * + * @return int Status code. + */ + public function getStatusCode() + { + return $this->status; + } + + /** + * Return an instance with the specified status code and, optionally, reason phrase. + * + * If no reason phrase is specified, implementations MAY choose to default + * to the RFC 7231 or IANA recommended reason phrase for the response's + * status code. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated status and reason phrase. + * + * @link http://tools.ietf.org/html/rfc7231#section-6 + * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml + * @param int $code The 3-digit integer result code to set. + * @param string $reasonPhrase The reason phrase to use with the + * provided status code; if none is provided, implementations MAY + * use the defaults as suggested in the HTTP specification. + * @return self + * @throws \InvalidArgumentException For invalid status code arguments. + */ + public function withStatus($code, $reasonPhrase = '') + { + $code = $this->filterStatus($code); + + if (!is_string($reasonPhrase) && !method_exists($reasonPhrase, '__toString')) { + throw new InvalidArgumentException('ReasonPhrase must be a string'); + } + + $clone = clone $this; + $clone->status = $code; + if ($reasonPhrase === '' && isset(static::$messages[$code])) { + $reasonPhrase = static::$messages[$code]; + } + + if ($reasonPhrase === '') { + throw new InvalidArgumentException('ReasonPhrase must be supplied for this code'); + } + + $clone->reasonPhrase = $reasonPhrase; + + return $clone; + } + + /** + * Filter HTTP status code. + * + * @param int $status HTTP status code. + * @return int + * @throws \InvalidArgumentException If an invalid HTTP status code is provided. + */ + protected function filterStatus($status) + { + if (!is_integer($status) || $status<100 || $status>599) { + throw new InvalidArgumentException('Invalid HTTP status code'); + } + + return $status; + } + + /** + * Gets the response reason phrase associated with the status code. + * + * Because a reason phrase is not a required element in a response + * status line, the reason phrase value MAY be null. Implementations MAY + * choose to return the default RFC 7231 recommended reason phrase (or those + * listed in the IANA HTTP Status Code Registry) for the response's + * status code. + * + * @link http://tools.ietf.org/html/rfc7231#section-6 + * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml + * @return string Reason phrase; must return an empty string if none present. + */ + public function getReasonPhrase() + { + if ($this->reasonPhrase) { + return $this->reasonPhrase; + } + if (isset(static::$messages[$this->status])) { + return static::$messages[$this->status]; + } + return ''; + } + + /******************************************************************************* + * Body + ******************************************************************************/ + + /** + * Write data to the response body. + * + * Note: This method is not part of the PSR-7 standard. + * + * Proxies to the underlying stream and writes the provided data to it. + * + * @param string $data + * @return self + */ + public function write($data) + { + $this->getBody()->write($data); + + return $this; + } + + /******************************************************************************* + * Response Helpers + ******************************************************************************/ + + /** + * Redirect. + * + * Note: This method is not part of the PSR-7 standard. + * + * This method prepares the response object to return an HTTP Redirect + * response to the client. + * + * @param string|UriInterface $url The redirect destination. + * @param int|null $status The redirect HTTP status code. + * @return self + */ + public function withRedirect($url, $status = null) + { + $responseWithRedirect = $this->withHeader('Location', (string)$url); + + if (is_null($status) && $this->getStatusCode() === 200) { + $status = 302; + } + + if (!is_null($status)) { + return $responseWithRedirect->withStatus($status); + } + + return $responseWithRedirect; + } + + /** + * Json. + * + * Note: This method is not part of the PSR-7 standard. + * + * This method prepares the response object to return an HTTP Json + * response to the client. + * + * @param mixed $data The data + * @param int $status The HTTP status code. + * @param int $encodingOptions Json encoding options + * @throws \RuntimeException + * @return self + */ + public function withJson($data, $status = null, $encodingOptions = 0) + { + $body = $this->getBody(); + $body->rewind(); + $body->write($json = json_encode($data, $encodingOptions)); + + // Ensure that the json encoding passed successfully + if ($json === false) { + throw new \RuntimeException(json_last_error_msg(), json_last_error()); + } + + $responseWithJson = $this->withHeader('Content-Type', 'application/json;charset=utf-8'); + if (isset($status)) { + return $responseWithJson->withStatus($status); + } + return $responseWithJson; + } + + /** + * Is this response empty? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isEmpty() + { + return in_array($this->getStatusCode(), [204, 205, 304]); + } + + /** + * Is this response informational? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isInformational() + { + return $this->getStatusCode() >= 100 && $this->getStatusCode() < 200; + } + + /** + * Is this response OK? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isOk() + { + return $this->getStatusCode() === 200; + } + + /** + * Is this response successful? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isSuccessful() + { + return $this->getStatusCode() >= 200 && $this->getStatusCode() < 300; + } + + /** + * Is this response a redirect? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isRedirect() + { + return in_array($this->getStatusCode(), [301, 302, 303, 307]); + } + + /** + * Is this response a redirection? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isRedirection() + { + return $this->getStatusCode() >= 300 && $this->getStatusCode() < 400; + } + + /** + * Is this response forbidden? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + * @api + */ + public function isForbidden() + { + return $this->getStatusCode() === 403; + } + + /** + * Is this response not Found? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isNotFound() + { + return $this->getStatusCode() === 404; + } + + /** + * Is this response a client error? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isClientError() + { + return $this->getStatusCode() >= 400 && $this->getStatusCode() < 500; + } + + /** + * Is this response a server error? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isServerError() + { + return $this->getStatusCode() >= 500 && $this->getStatusCode() < 600; + } + + /** + * Convert response to string. + * + * Note: This method is not part of the PSR-7 standard. + * + * @return string + */ + public function __toString() + { + $output = sprintf( + 'HTTP/%s %s %s', + $this->getProtocolVersion(), + $this->getStatusCode(), + $this->getReasonPhrase() + ); + $output .= PHP_EOL; + foreach ($this->getHeaders() as $name => $values) { + $output .= sprintf('%s: %s', $name, $this->getHeaderLine($name)) . PHP_EOL; + } + $output .= PHP_EOL; + $output .= (string)$this->getBody(); + + return $output; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Stream.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Stream.php new file mode 100644 index 000000000000..97de9ac0090a --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Stream.php @@ -0,0 +1,409 @@ + ['r', 'r+', 'w+', 'a+', 'x+', 'c+'], + 'writable' => ['r+', 'w', 'w+', 'a', 'a+', 'x', 'x+', 'c', 'c+'], + ]; + + /** + * The underlying stream resource + * + * @var resource + */ + protected $stream; + + /** + * Stream metadata + * + * @var array + */ + protected $meta; + + /** + * Is this stream readable? + * + * @var bool + */ + protected $readable; + + /** + * Is this stream writable? + * + * @var bool + */ + protected $writable; + + /** + * Is this stream seekable? + * + * @var bool + */ + protected $seekable; + + /** + * The size of the stream if known + * + * @var null|int + */ + protected $size; + + /** + * Create a new Stream. + * + * @param resource $stream A PHP resource handle. + * + * @throws InvalidArgumentException If argument is not a resource. + */ + public function __construct($stream) + { + $this->attach($stream); + } + + /** + * Get stream metadata as an associative array or retrieve a specific key. + * + * The keys returned are identical to the keys returned from PHP's + * stream_get_meta_data() function. + * + * @link http://php.net/manual/en/function.stream-get-meta-data.php + * + * @param string $key Specific metadata to retrieve. + * + * @return array|mixed|null Returns an associative array if no key is + * provided. Returns a specific key value if a key is provided and the + * value is found, or null if the key is not found. + */ + public function getMetadata($key = null) + { + $this->meta = stream_get_meta_data($this->stream); + if (is_null($key) === true) { + return $this->meta; + } + + return isset($this->meta[$key]) ? $this->meta[$key] : null; + } + + /** + * Is a resource attached to this stream? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + protected function isAttached() + { + return is_resource($this->stream); + } + + /** + * Attach new resource to this object. + * + * Note: This method is not part of the PSR-7 standard. + * + * @param resource $newStream A PHP resource handle. + * + * @throws InvalidArgumentException If argument is not a valid PHP resource. + */ + protected function attach($newStream) + { + if (is_resource($newStream) === false) { + throw new InvalidArgumentException(__METHOD__ . ' argument must be a valid PHP resource'); + } + + if ($this->isAttached() === true) { + $this->detach(); + } + + $this->stream = $newStream; + } + + /** + * Separates any underlying resources from the stream. + * + * After the stream has been detached, the stream is in an unusable state. + * + * @return resource|null Underlying PHP stream, if any + */ + public function detach() + { + $oldResource = $this->stream; + $this->stream = null; + $this->meta = null; + $this->readable = null; + $this->writable = null; + $this->seekable = null; + $this->size = null; + + return $oldResource; + } + + /** + * Reads all data from the stream into a string, from the beginning to end. + * + * This method MUST attempt to seek to the beginning of the stream before + * reading data and read the stream until the end is reached. + * + * Warning: This could attempt to load a large amount of data into memory. + * + * This method MUST NOT raise an exception in order to conform with PHP's + * string casting operations. + * + * @see http://php.net/manual/en/language.oop5.magic.php#object.tostring + * @return string + */ + public function __toString() + { + if (!$this->isAttached()) { + return ''; + } + + try { + $this->rewind(); + return $this->getContents(); + } catch (RuntimeException $e) { + return ''; + } + } + + /** + * Closes the stream and any underlying resources. + */ + public function close() + { + if ($this->isAttached() === true) { + fclose($this->stream); + } + + $this->detach(); + } + + /** + * Get the size of the stream if known. + * + * @return int|null Returns the size in bytes if known, or null if unknown. + */ + public function getSize() + { + if (!$this->size && $this->isAttached() === true) { + $stats = fstat($this->stream); + $this->size = isset($stats['size']) ? $stats['size'] : null; + } + + return $this->size; + } + + /** + * Returns the current position of the file read/write pointer + * + * @return int Position of the file pointer + * + * @throws RuntimeException on error. + */ + public function tell() + { + if (!$this->isAttached() || ($position = ftell($this->stream)) === false) { + throw new RuntimeException('Could not get the position of the pointer in stream'); + } + + return $position; + } + + /** + * Returns true if the stream is at the end of the stream. + * + * @return bool + */ + public function eof() + { + return $this->isAttached() ? feof($this->stream) : true; + } + + /** + * Returns whether or not the stream is readable. + * + * @return bool + */ + public function isReadable() + { + if ($this->readable === null) { + $this->readable = false; + if ($this->isAttached()) { + $meta = $this->getMetadata(); + foreach (self::$modes['readable'] as $mode) { + if (strpos($meta['mode'], $mode) === 0) { + $this->readable = true; + break; + } + } + } + } + + return $this->readable; + } + + /** + * Returns whether or not the stream is writable. + * + * @return bool + */ + public function isWritable() + { + if ($this->writable === null) { + $this->writable = false; + if ($this->isAttached()) { + $meta = $this->getMetadata(); + foreach (self::$modes['writable'] as $mode) { + if (strpos($meta['mode'], $mode) === 0) { + $this->writable = true; + break; + } + } + } + } + + return $this->writable; + } + + /** + * Returns whether or not the stream is seekable. + * + * @return bool + */ + public function isSeekable() + { + if ($this->seekable === null) { + $this->seekable = false; + if ($this->isAttached()) { + $meta = $this->getMetadata(); + $this->seekable = $meta['seekable']; + } + } + + return $this->seekable; + } + + /** + * Seek to a position in the stream. + * + * @link http://www.php.net/manual/en/function.fseek.php + * + * @param int $offset Stream offset + * @param int $whence Specifies how the cursor position will be calculated + * based on the seek offset. Valid values are identical to the built-in + * PHP $whence values for `fseek()`. SEEK_SET: Set position equal to + * offset bytes SEEK_CUR: Set position to current location plus offset + * SEEK_END: Set position to end-of-stream plus offset. + * + * @throws RuntimeException on failure. + */ + public function seek($offset, $whence = SEEK_SET) + { + // Note that fseek returns 0 on success! + if (!$this->isSeekable() || fseek($this->stream, $offset, $whence) === -1) { + throw new RuntimeException('Could not seek in stream'); + } + } + + /** + * Seek to the beginning of the stream. + * + * If the stream is not seekable, this method will raise an exception; + * otherwise, it will perform a seek(0). + * + * @see seek() + * + * @link http://www.php.net/manual/en/function.fseek.php + * + * @throws RuntimeException on failure. + */ + public function rewind() + { + if (!$this->isSeekable() || rewind($this->stream) === false) { + throw new RuntimeException('Could not rewind stream'); + } + } + + /** + * Read data from the stream. + * + * @param int $length Read up to $length bytes from the object and return + * them. Fewer than $length bytes may be returned if underlying stream + * call returns fewer bytes. + * + * @return string Returns the data read from the stream, or an empty string + * if no bytes are available. + * + * @throws RuntimeException if an error occurs. + */ + public function read($length) + { + if (!$this->isReadable() || ($data = fread($this->stream, $length)) === false) { + throw new RuntimeException('Could not read from stream'); + } + + return $data; + } + + /** + * Write data to the stream. + * + * @param string $string The string that is to be written. + * + * @return int Returns the number of bytes written to the stream. + * + * @throws RuntimeException on failure. + */ + public function write($string) + { + if (!$this->isWritable() || ($written = fwrite($this->stream, $string)) === false) { + throw new RuntimeException('Could not write to stream'); + } + + // reset size so that it will be recalculated on next call to getSize() + $this->size = null; + + return $written; + } + + /** + * Returns the remaining contents in a string + * + * @return string + * + * @throws RuntimeException if unable to read or an error occurs while + * reading. + */ + public function getContents() + { + if (!$this->isReadable() || ($contents = stream_get_contents($this->stream)) === false) { + throw new RuntimeException('Could not get contents of stream'); + } + + return $contents; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/UploadedFile.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/UploadedFile.php new file mode 100644 index 000000000000..ff970277c7c7 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/UploadedFile.php @@ -0,0 +1,327 @@ +has('slim.files')) { + return $env['slim.files']; + } elseif (isset($_FILES)) { + return static::parseUploadedFiles($_FILES); + } + + return []; + } + + /** + * Parse a non-normalized, i.e. $_FILES superglobal, tree of uploaded file data. + * + * @param array $uploadedFiles The non-normalized tree of uploaded file data. + * + * @return array A normalized tree of UploadedFile instances. + */ + private static function parseUploadedFiles(array $uploadedFiles) + { + $parsed = []; + foreach ($uploadedFiles as $field => $uploadedFile) { + if (!isset($uploadedFile['error'])) { + if (is_array($uploadedFile)) { + $parsed[$field] = static::parseUploadedFiles($uploadedFile); + } + continue; + } + + $parsed[$field] = []; + if (!is_array($uploadedFile['error'])) { + $parsed[$field] = new static( + $uploadedFile['tmp_name'], + isset($uploadedFile['name']) ? $uploadedFile['name'] : null, + isset($uploadedFile['type']) ? $uploadedFile['type'] : null, + isset($uploadedFile['size']) ? $uploadedFile['size'] : null, + $uploadedFile['error'], + true + ); + } else { + $subArray = []; + foreach ($uploadedFile['error'] as $fileIdx => $error) { + // normalise subarray and re-parse to move the input's keyname up a level + $subArray[$fileIdx]['name'] = $uploadedFile['name'][$fileIdx]; + $subArray[$fileIdx]['type'] = $uploadedFile['type'][$fileIdx]; + $subArray[$fileIdx]['tmp_name'] = $uploadedFile['tmp_name'][$fileIdx]; + $subArray[$fileIdx]['error'] = $uploadedFile['error'][$fileIdx]; + $subArray[$fileIdx]['size'] = $uploadedFile['size'][$fileIdx]; + + $parsed[$field] = static::parseUploadedFiles($subArray); + } + } + } + + return $parsed; + } + + /** + * Construct a new UploadedFile instance. + * + * @param string $file The full path to the uploaded file provided by the client. + * @param string|null $name The file name. + * @param string|null $type The file media type. + * @param int|null $size The file size in bytes. + * @param int $error The UPLOAD_ERR_XXX code representing the status of the upload. + * @param bool $sapi Indicates if the upload is in a SAPI environment. + */ + public function __construct($file, $name = null, $type = null, $size = null, $error = UPLOAD_ERR_OK, $sapi = false) + { + $this->file = $file; + $this->name = $name; + $this->type = $type; + $this->size = $size; + $this->error = $error; + $this->sapi = $sapi; + } + + /** + * Retrieve a stream representing the uploaded file. + * + * This method MUST return a StreamInterface instance, representing the + * uploaded file. The purpose of this method is to allow utilizing native PHP + * stream functionality to manipulate the file upload, such as + * stream_copy_to_stream() (though the result will need to be decorated in a + * native PHP stream wrapper to work with such functions). + * + * If the moveTo() method has been called previously, this method MUST raise + * an exception. + * + * @return StreamInterface Stream representation of the uploaded file. + * @throws \RuntimeException in cases when no stream is available or can be + * created. + */ + public function getStream() + { + if ($this->moved) { + throw new \RuntimeException(sprintf('Uploaded file %1s has already been moved', $this->name)); + } + if ($this->stream === null) { + $this->stream = new Stream(fopen($this->file, 'r')); + } + + return $this->stream; + } + + /** + * Move the uploaded file to a new location. + * + * Use this method as an alternative to move_uploaded_file(). This method is + * guaranteed to work in both SAPI and non-SAPI environments. + * Implementations must determine which environment they are in, and use the + * appropriate method (move_uploaded_file(), rename(), or a stream + * operation) to perform the operation. + * + * $targetPath may be an absolute path, or a relative path. If it is a + * relative path, resolution should be the same as used by PHP's rename() + * function. + * + * The original file or stream MUST be removed on completion. + * + * If this method is called more than once, any subsequent calls MUST raise + * an exception. + * + * When used in an SAPI environment where $_FILES is populated, when writing + * files via moveTo(), is_uploaded_file() and move_uploaded_file() SHOULD be + * used to ensure permissions and upload status are verified correctly. + * + * If you wish to move to a stream, use getStream(), as SAPI operations + * cannot guarantee writing to stream destinations. + * + * @see http://php.net/is_uploaded_file + * @see http://php.net/move_uploaded_file + * + * @param string $targetPath Path to which to move the uploaded file. + * + * @throws InvalidArgumentException if the $path specified is invalid. + * @throws RuntimeException on any error during the move operation, or on + * the second or subsequent call to the method. + */ + public function moveTo($targetPath) + { + if ($this->moved) { + throw new RuntimeException('Uploaded file already moved'); + } + + if (!is_writable(dirname($targetPath))) { + throw new InvalidArgumentException('Upload target path is not writable'); + } + + $targetIsStream = strpos($targetPath, '://') > 0; + if ($targetIsStream) { + if (!copy($this->file, $targetPath)) { + throw new RuntimeException(sprintf('Error moving uploaded file %1s to %2s', $this->name, $targetPath)); + } + if (!unlink($this->file)) { + throw new RuntimeException(sprintf('Error removing uploaded file %1s', $this->name)); + } + } elseif ($this->sapi) { + if (!is_uploaded_file($this->file)) { + throw new RuntimeException(sprintf('%1s is not a valid uploaded file', $this->file)); + } + + if (!move_uploaded_file($this->file, $targetPath)) { + throw new RuntimeException(sprintf('Error moving uploaded file %1s to %2s', $this->name, $targetPath)); + } + } else { + if (!rename($this->file, $targetPath)) { + throw new RuntimeException(sprintf('Error moving uploaded file %1s to %2s', $this->name, $targetPath)); + } + } + + $this->moved = true; + } + + /** + * Retrieve the error associated with the uploaded file. + * + * The return value MUST be one of PHP's UPLOAD_ERR_XXX constants. + * + * If the file was uploaded successfully, this method MUST return + * UPLOAD_ERR_OK. + * + * Implementations SHOULD return the value stored in the "error" key of + * the file in the $_FILES array. + * + * @see http://php.net/manual/en/features.file-upload.errors.php + * + * @return int One of PHP's UPLOAD_ERR_XXX constants. + */ + public function getError() + { + return $this->error; + } + + /** + * Retrieve the filename sent by the client. + * + * Do not trust the value returned by this method. A client could send + * a malicious filename with the intention to corrupt or hack your + * application. + * + * Implementations SHOULD return the value stored in the "name" key of + * the file in the $_FILES array. + * + * @return string|null The filename sent by the client or null if none + * was provided. + */ + public function getClientFilename() + { + return $this->name; + } + + /** + * Retrieve the media type sent by the client. + * + * Do not trust the value returned by this method. A client could send + * a malicious media type with the intention to corrupt or hack your + * application. + * + * Implementations SHOULD return the value stored in the "type" key of + * the file in the $_FILES array. + * + * @return string|null The media type sent by the client or null if none + * was provided. + */ + public function getClientMediaType() + { + return $this->type; + } + + /** + * Retrieve the file size. + * + * Implementations SHOULD return the value stored in the "size" key of + * the file in the $_FILES array if available, as PHP calculates this based + * on the actual size transmitted. + * + * @return int|null The file size in bytes or null if unknown. + */ + public function getSize() + { + return $this->size; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Uri.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Uri.php new file mode 100644 index 000000000000..27b1d0d59389 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Http/Uri.php @@ -0,0 +1,821 @@ +scheme = $this->filterScheme($scheme); + $this->host = $host; + $this->port = $this->filterPort($port); + $this->path = empty($path) ? '/' : $this->filterPath($path); + $this->query = $this->filterQuery($query); + $this->fragment = $this->filterQuery($fragment); + $this->user = $user; + $this->password = $password; + } + + /** + * Create new Uri from string. + * + * @param string $uri Complete Uri string + * (i.e., https://user:pass@host:443/path?query). + * + * @return self + */ + public static function createFromString($uri) + { + if (!is_string($uri) && !method_exists($uri, '__toString')) { + throw new InvalidArgumentException('Uri must be a string'); + } + + $parts = parse_url($uri); + $scheme = isset($parts['scheme']) ? $parts['scheme'] : ''; + $user = isset($parts['user']) ? $parts['user'] : ''; + $pass = isset($parts['pass']) ? $parts['pass'] : ''; + $host = isset($parts['host']) ? $parts['host'] : ''; + $port = isset($parts['port']) ? $parts['port'] : null; + $path = isset($parts['path']) ? $parts['path'] : ''; + $query = isset($parts['query']) ? $parts['query'] : ''; + $fragment = isset($parts['fragment']) ? $parts['fragment'] : ''; + + return new static($scheme, $host, $port, $path, $query, $fragment, $user, $pass); + } + + /** + * Create new Uri from environment. + * + * @param Environment $env + * + * @return self + */ + public static function createFromEnvironment(Environment $env) + { + // Scheme + $isSecure = $env->get('HTTPS'); + $scheme = (empty($isSecure) || $isSecure === 'off') ? 'http' : 'https'; + + // Authority: Username and password + $username = $env->get('PHP_AUTH_USER', ''); + $password = $env->get('PHP_AUTH_PW', ''); + + // Authority: Host + if ($env->has('HTTP_HOST')) { + $host = $env->get('HTTP_HOST'); + } else { + $host = $env->get('SERVER_NAME'); + } + + // Authority: Port + $port = (int)$env->get('SERVER_PORT', 80); + if (preg_match('/^(\[[a-fA-F0-9:.]+\])(:\d+)?\z/', $host, $matches)) { + $host = $matches[1]; + + if ($matches[2]) { + $port = (int) substr($matches[2], 1); + } + } else { + $pos = strpos($host, ':'); + if ($pos !== false) { + $port = (int) substr($host, $pos + 1); + $host = strstr($host, ':', true); + } + } + + // Path + $requestScriptName = parse_url($env->get('SCRIPT_NAME'), PHP_URL_PATH); + $requestScriptDir = dirname($requestScriptName); + + // parse_url() requires a full URL. As we don't extract the domain name or scheme, + // we use a stand-in. + $requestUri = parse_url('http://example.com' . $env->get('REQUEST_URI'), PHP_URL_PATH); + + $basePath = ''; + $virtualPath = $requestUri; + if (stripos($requestUri, $requestScriptName) === 0) { + $basePath = $requestScriptName; + } elseif ($requestScriptDir !== '/' && stripos($requestUri, $requestScriptDir) === 0) { + $basePath = $requestScriptDir; + } + + if ($basePath) { + $virtualPath = ltrim(substr($requestUri, strlen($basePath)), '/'); + } + + // Query string + $queryString = $env->get('QUERY_STRING', ''); + + // Fragment + $fragment = ''; + + // Build Uri + $uri = new static($scheme, $host, $port, $virtualPath, $queryString, $fragment, $username, $password); + if ($basePath) { + $uri = $uri->withBasePath($basePath); + } + + return $uri; + } + + /******************************************************************************** + * Scheme + *******************************************************************************/ + + /** + * Retrieve the scheme component of the URI. + * + * If no scheme is present, this method MUST return an empty string. + * + * The value returned MUST be normalized to lowercase, per RFC 3986 + * Section 3.1. + * + * The trailing ":" character is not part of the scheme and MUST NOT be + * added. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.1 + * @return string The URI scheme. + */ + public function getScheme() + { + return $this->scheme; + } + + /** + * Return an instance with the specified scheme. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified scheme. + * + * Implementations MUST support the schemes "http" and "https" case + * insensitively, and MAY accommodate other schemes if required. + * + * An empty scheme is equivalent to removing the scheme. + * + * @param string $scheme The scheme to use with the new instance. + * @return self A new instance with the specified scheme. + * @throws \InvalidArgumentException for invalid or unsupported schemes. + */ + public function withScheme($scheme) + { + $scheme = $this->filterScheme($scheme); + $clone = clone $this; + $clone->scheme = $scheme; + + return $clone; + } + + /** + * Filter Uri scheme. + * + * @param string $scheme Raw Uri scheme. + * @return string + * + * @throws InvalidArgumentException If the Uri scheme is not a string. + * @throws InvalidArgumentException If Uri scheme is not "", "https", or "http". + */ + protected function filterScheme($scheme) + { + static $valid = [ + '' => true, + 'https' => true, + 'http' => true, + ]; + + if (!is_string($scheme) && !method_exists($scheme, '__toString')) { + throw new InvalidArgumentException('Uri scheme must be a string'); + } + + $scheme = str_replace('://', '', strtolower((string)$scheme)); + if (!isset($valid[$scheme])) { + throw new InvalidArgumentException('Uri scheme must be one of: "", "https", "http"'); + } + + return $scheme; + } + + /******************************************************************************** + * Authority + *******************************************************************************/ + + /** + * Retrieve the authority component of the URI. + * + * If no authority information is present, this method MUST return an empty + * string. + * + * The authority syntax of the URI is: + * + *
+     * [user-info@]host[:port]
+     * 
+ * + * If the port component is not set or is the standard port for the current + * scheme, it SHOULD NOT be included. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.2 + * @return string The URI authority, in "[user-info@]host[:port]" format. + */ + public function getAuthority() + { + $userInfo = $this->getUserInfo(); + $host = $this->getHost(); + $port = $this->getPort(); + + return ($userInfo ? $userInfo . '@' : '') . $host . ($port !== null ? ':' . $port : ''); + } + + /** + * Retrieve the user information component of the URI. + * + * If no user information is present, this method MUST return an empty + * string. + * + * If a user is present in the URI, this will return that value; + * additionally, if the password is also present, it will be appended to the + * user value, with a colon (":") separating the values. + * + * The trailing "@" character is not part of the user information and MUST + * NOT be added. + * + * @return string The URI user information, in "username[:password]" format. + */ + public function getUserInfo() + { + return $this->user . ($this->password ? ':' . $this->password : ''); + } + + /** + * Return an instance with the specified user information. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified user information. + * + * Password is optional, but the user information MUST include the + * user; an empty string for the user is equivalent to removing user + * information. + * + * @param string $user The user name to use for authority. + * @param null|string $password The password associated with $user. + * @return self A new instance with the specified user information. + */ + public function withUserInfo($user, $password = null) + { + $clone = clone $this; + $clone->user = $user; + $clone->password = $password ? $password : ''; + + return $clone; + } + + /** + * Retrieve the host component of the URI. + * + * If no host is present, this method MUST return an empty string. + * + * The value returned MUST be normalized to lowercase, per RFC 3986 + * Section 3.2.2. + * + * @see http://tools.ietf.org/html/rfc3986#section-3.2.2 + * @return string The URI host. + */ + public function getHost() + { + return $this->host; + } + + /** + * Return an instance with the specified host. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified host. + * + * An empty host value is equivalent to removing the host. + * + * @param string $host The hostname to use with the new instance. + * @return self A new instance with the specified host. + * @throws \InvalidArgumentException for invalid hostnames. + */ + public function withHost($host) + { + $clone = clone $this; + $clone->host = $host; + + return $clone; + } + + /** + * Retrieve the port component of the URI. + * + * If a port is present, and it is non-standard for the current scheme, + * this method MUST return it as an integer. If the port is the standard port + * used with the current scheme, this method SHOULD return null. + * + * If no port is present, and no scheme is present, this method MUST return + * a null value. + * + * If no port is present, but a scheme is present, this method MAY return + * the standard port for that scheme, but SHOULD return null. + * + * @return null|int The URI port. + */ + public function getPort() + { + return $this->port && !$this->hasStandardPort() ? $this->port : null; + } + + /** + * Return an instance with the specified port. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified port. + * + * Implementations MUST raise an exception for ports outside the + * established TCP and UDP port ranges. + * + * A null value provided for the port is equivalent to removing the port + * information. + * + * @param null|int $port The port to use with the new instance; a null value + * removes the port information. + * @return self A new instance with the specified port. + * @throws \InvalidArgumentException for invalid ports. + */ + public function withPort($port) + { + $port = $this->filterPort($port); + $clone = clone $this; + $clone->port = $port; + + return $clone; + } + + /** + * Does this Uri use a standard port? + * + * @return bool + */ + protected function hasStandardPort() + { + return ($this->scheme === 'http' && $this->port === 80) || ($this->scheme === 'https' && $this->port === 443); + } + + /** + * Filter Uri port. + * + * @param null|int $port The Uri port number. + * @return null|int + * + * @throws InvalidArgumentException If the port is invalid. + */ + protected function filterPort($port) + { + if (is_null($port) || (is_integer($port) && ($port >= 1 && $port <= 65535))) { + return $port; + } + + throw new InvalidArgumentException('Uri port must be null or an integer between 1 and 65535 (inclusive)'); + } + + /******************************************************************************** + * Path + *******************************************************************************/ + + /** + * Retrieve the path component of the URI. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * Normally, the empty path "" and absolute path "/" are considered equal as + * defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically + * do this normalization because in contexts with a trimmed base path, e.g. + * the front controller, this difference becomes significant. It's the task + * of the user to handle both "" and "/". + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.3. + * + * As an example, if the value should include a slash ("/") not intended as + * delimiter between path segments, that value MUST be passed in encoded + * form (e.g., "%2F") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.3 + * @return string The URI path. + */ + public function getPath() + { + return $this->path; + } + + /** + * Return an instance with the specified path. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified path. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * If the path is intended to be domain-relative rather than path relative then + * it must begin with a slash ("/"). Paths not starting with a slash ("/") + * are assumed to be relative to some base path known to the application or + * consumer. + * + * Users can provide both encoded and decoded path characters. + * Implementations ensure the correct encoding as outlined in getPath(). + * + * @param string $path The path to use with the new instance. + * @return self A new instance with the specified path. + * @throws \InvalidArgumentException for invalid paths. + */ + public function withPath($path) + { + if (!is_string($path)) { + throw new InvalidArgumentException('Uri path must be a string'); + } + + $clone = clone $this; + $clone->path = $this->filterPath($path); + + // if the path is absolute, then clear basePath + if (substr($path, 0, 1) == '/') { + $clone->basePath = ''; + } + + return $clone; + } + + /** + * Retrieve the base path segment of the URI. + * + * Note: This method is not part of the PSR-7 standard. + * + * This method MUST return a string; if no path is present it MUST return + * an empty string. + * + * @return string The base path segment of the URI. + */ + public function getBasePath() + { + return $this->basePath; + } + + /** + * Set base path. + * + * Note: This method is not part of the PSR-7 standard. + * + * @param string $basePath + * @return self + */ + public function withBasePath($basePath) + { + if (!is_string($basePath)) { + throw new InvalidArgumentException('Uri path must be a string'); + } + if (!empty($basePath)) { + $basePath = '/' . trim($basePath, '/'); // <-- Trim on both sides + } + $clone = clone $this; + + if ($basePath !== '/') { + $clone->basePath = $this->filterPath($basePath); + } + + return $clone; + } + + /** + * Filter Uri path. + * + * This method percent-encodes all reserved + * characters in the provided path string. This method + * will NOT double-encode characters that are already + * percent-encoded. + * + * @param string $path The raw uri path. + * @return string The RFC 3986 percent-encoded uri path. + * @link http://www.faqs.org/rfcs/rfc3986.html + */ + protected function filterPath($path) + { + return preg_replace_callback( + '/(?:[^a-zA-Z0-9_\-\.~:@&=\+\$,\/;%]+|%(?![A-Fa-f0-9]{2}))/', + function ($match) { + return rawurlencode($match[0]); + }, + $path + ); + } + + /******************************************************************************** + * Query + *******************************************************************************/ + + /** + * Retrieve the query string of the URI. + * + * If no query string is present, this method MUST return an empty string. + * + * The leading "?" character is not part of the query and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.4. + * + * As an example, if a value in a key/value pair of the query string should + * include an ampersand ("&") not intended as a delimiter between values, + * that value MUST be passed in encoded form (e.g., "%26") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.4 + * @return string The URI query string. + */ + public function getQuery() + { + return $this->query; + } + + /** + * Return an instance with the specified query string. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified query string. + * + * Users can provide both encoded and decoded query characters. + * Implementations ensure the correct encoding as outlined in getQuery(). + * + * An empty query string value is equivalent to removing the query string. + * + * @param string $query The query string to use with the new instance. + * @return self A new instance with the specified query string. + * @throws \InvalidArgumentException for invalid query strings. + */ + public function withQuery($query) + { + if (!is_string($query) && !method_exists($query, '__toString')) { + throw new InvalidArgumentException('Uri query must be a string'); + } + $query = ltrim((string)$query, '?'); + $clone = clone $this; + $clone->query = $this->filterQuery($query); + + return $clone; + } + + /** + * Filters the query string or fragment of a URI. + * + * @param string $query The raw uri query string. + * @return string The percent-encoded query string. + */ + protected function filterQuery($query) + { + return preg_replace_callback( + '/(?:[^a-zA-Z0-9_\-\.~!\$&\'\(\)\*\+,;=%:@\/\?]+|%(?![A-Fa-f0-9]{2}))/', + function ($match) { + return rawurlencode($match[0]); + }, + $query + ); + } + + /******************************************************************************** + * Fragment + *******************************************************************************/ + + /** + * Retrieve the fragment component of the URI. + * + * If no fragment is present, this method MUST return an empty string. + * + * The leading "#" character is not part of the fragment and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.5. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.5 + * @return string The URI fragment. + */ + public function getFragment() + { + return $this->fragment; + } + + /** + * Return an instance with the specified URI fragment. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified URI fragment. + * + * Users can provide both encoded and decoded fragment characters. + * Implementations ensure the correct encoding as outlined in getFragment(). + * + * An empty fragment value is equivalent to removing the fragment. + * + * @param string $fragment The fragment to use with the new instance. + * @return self A new instance with the specified fragment. + */ + public function withFragment($fragment) + { + if (!is_string($fragment) && !method_exists($fragment, '__toString')) { + throw new InvalidArgumentException('Uri fragment must be a string'); + } + $fragment = ltrim((string)$fragment, '#'); + $clone = clone $this; + $clone->fragment = $this->filterQuery($fragment); + + return $clone; + } + + /******************************************************************************** + * Helpers + *******************************************************************************/ + + /** + * Return the string representation as a URI reference. + * + * Depending on which components of the URI are present, the resulting + * string is either a full URI or relative reference according to RFC 3986, + * Section 4.1. The method concatenates the various components of the URI, + * using the appropriate delimiters: + * + * - If a scheme is present, it MUST be suffixed by ":". + * - If an authority is present, it MUST be prefixed by "//". + * - The path can be concatenated without delimiters. But there are two + * cases where the path has to be adjusted to make the URI reference + * valid as PHP does not allow to throw an exception in __toString(): + * - If the path is rootless and an authority is present, the path MUST + * be prefixed by "/". + * - If the path is starting with more than one "/" and no authority is + * present, the starting slashes MUST be reduced to one. + * - If a query is present, it MUST be prefixed by "?". + * - If a fragment is present, it MUST be prefixed by "#". + * + * @see http://tools.ietf.org/html/rfc3986#section-4.1 + * @return string + */ + public function __toString() + { + $scheme = $this->getScheme(); + $authority = $this->getAuthority(); + $basePath = $this->getBasePath(); + $path = $this->getPath(); + $query = $this->getQuery(); + $fragment = $this->getFragment(); + + $path = $basePath . '/' . ltrim($path, '/'); + + return ($scheme ? $scheme . ':' : '') + . ($authority ? '//' . $authority : '') + . $path + . ($query ? '?' . $query : '') + . ($fragment ? '#' . $fragment : ''); + } + + /** + * Return the fully qualified base URL. + * + * Note that this method never includes a trailing / + * + * This method is not part of PSR-7. + * + * @return string + */ + public function getBaseUrl() + { + $scheme = $this->getScheme(); + $authority = $this->getAuthority(); + $basePath = $this->getBasePath(); + + if ($authority && substr($basePath, 0, 1) !== '/') { + $basePath = $basePath . '/' . $basePath; + } + + return ($scheme ? $scheme . ':' : '') + . ($authority ? '//' . $authority : '') + . rtrim($basePath, '/'); + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Interfaces/CallableResolverInterface.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Interfaces/CallableResolverInterface.php new file mode 100644 index 000000000000..9bde59ac97a7 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Interfaces/CallableResolverInterface.php @@ -0,0 +1,27 @@ +middlewareLock) { + throw new RuntimeException('Middleware can’t be added once the stack is dequeuing'); + } + + if (is_null($this->stack)) { + $this->seedMiddlewareStack(); + } + $next = $this->stack->top(); + $this->stack[] = function (ServerRequestInterface $req, ResponseInterface $res) use ($callable, $next) { + $result = call_user_func($callable, $req, $res, $next); + if ($result instanceof ResponseInterface === false) { + throw new UnexpectedValueException( + 'Middleware must return instance of \Psr\Http\Message\ResponseInterface' + ); + } + + return $result; + }; + + return $this; + } + + /** + * Seed middleware stack with first callable + * + * @param callable $kernel The last item to run as middleware + * + * @throws RuntimeException if the stack is seeded more than once + */ + protected function seedMiddlewareStack(callable $kernel = null) + { + if (!is_null($this->stack)) { + throw new RuntimeException('MiddlewareStack can only be seeded once.'); + } + if ($kernel === null) { + $kernel = $this; + } + $this->stack = new SplStack; + $this->stack->setIteratorMode(SplDoublyLinkedList::IT_MODE_LIFO | SplDoublyLinkedList::IT_MODE_KEEP); + $this->stack[] = $kernel; + } + + /** + * Call middleware stack + * + * @param ServerRequestInterface $req A request object + * @param ResponseInterface $res A response object + * + * @return ResponseInterface + */ + public function callMiddlewareStack(ServerRequestInterface $req, ResponseInterface $res) + { + if (is_null($this->stack)) { + $this->seedMiddlewareStack(); + } + /** @var callable $start */ + $start = $this->stack->top(); + $this->middlewareLock = true; + $resp = $start($req, $res); + $this->middlewareLock = false; + return $resp; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Routable.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Routable.php new file mode 100644 index 000000000000..4a6759fac469 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Routable.php @@ -0,0 +1,106 @@ +middleware; + } + + /** + * Get the route pattern + * + * @return string + */ + public function getPattern() + { + return $this->pattern; + } + + /** + * Set container for use with resolveCallable + * + * @param ContainerInterface $container + * + * @return self + */ + public function setContainer(ContainerInterface $container) + { + $this->container = $container; + return $this; + } + + /** + * Prepend middleware to the middleware collection + * + * @param callable|string $callable The callback routine + * + * @return static + */ + public function add($callable) + { + $this->middleware[] = new DeferredCallable($callable, $this->container); + return $this; + } + + /** + * Set the route pattern + * + * @set string + */ + public function setPattern($newPattern) + { + $this->pattern = $newPattern; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Route.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Route.php new file mode 100644 index 000000000000..3cb4a0e28b4a --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Route.php @@ -0,0 +1,357 @@ +methods = $methods; + $this->pattern = $pattern; + $this->callable = $callable; + $this->groups = $groups; + $this->identifier = 'route' . $identifier; + } + + /** + * Finalize the route in preparation for dispatching + */ + public function finalize() + { + if ($this->finalized) { + return; + } + + $groupMiddleware = []; + foreach ($this->getGroups() as $group) { + $groupMiddleware = array_merge($group->getMiddleware(), $groupMiddleware); + } + + $this->middleware = array_merge($this->middleware, $groupMiddleware); + + foreach ($this->getMiddleware() as $middleware) { + $this->addMiddleware($middleware); + } + + $this->finalized = true; + } + + /** + * Get route callable + * + * @return callable + */ + public function getCallable() + { + return $this->callable; + } + + /** + * Get route methods + * + * @return string[] + */ + public function getMethods() + { + return $this->methods; + } + + /** + * Get parent route groups + * + * @return RouteGroup[] + */ + public function getGroups() + { + return $this->groups; + } + + /** + * Get route name + * + * @return null|string + */ + public function getName() + { + return $this->name; + } + + /** + * Get route identifier + * + * @return string + */ + public function getIdentifier() + { + return $this->identifier; + } + + /** + * Get output buffering mode + * + * @return boolean|string + */ + public function getOutputBuffering() + { + return $this->outputBuffering; + } + + /** + * Set output buffering mode + * + * One of: false, 'prepend' or 'append' + * + * @param boolean|string $mode + * + * @throws InvalidArgumentException If an unknown buffering mode is specified + */ + public function setOutputBuffering($mode) + { + if (!in_array($mode, [false, 'prepend', 'append'], true)) { + throw new InvalidArgumentException('Unknown output buffering mode'); + } + $this->outputBuffering = $mode; + } + + /** + * Set route name + * + * @param string $name + * + * @return self + * + * @throws InvalidArgumentException if the route name is not a string + */ + public function setName($name) + { + if (!is_string($name)) { + throw new InvalidArgumentException('Route name must be a string'); + } + $this->name = $name; + return $this; + } + + /** + * Set a route argument + * + * @param string $name + * @param string $value + * + * @return self + */ + public function setArgument($name, $value) + { + $this->arguments[$name] = $value; + return $this; + } + + /** + * Replace route arguments + * + * @param array $arguments + * + * @return self + */ + public function setArguments(array $arguments) + { + $this->arguments = $arguments; + return $this; + } + + /** + * Retrieve route arguments + * + * @return array + */ + public function getArguments() + { + return $this->arguments; + } + + /** + * Retrieve a specific route argument + * + * @param string $name + * @param mixed $default + * + * @return mixed + */ + public function getArgument($name, $default = null) + { + if (array_key_exists($name, $this->arguments)) { + return $this->arguments[$name]; + } + return $default; + } + + /******************************************************************************** + * Route Runner + *******************************************************************************/ + + /** + * Prepare the route for use + * + * @param ServerRequestInterface $request + * @param array $arguments + */ + public function prepare(ServerRequestInterface $request, array $arguments) + { + // Add the arguments + foreach ($arguments as $k => $v) { + $this->setArgument($k, $v); + } + } + + /** + * Run route + * + * This method traverses the middleware stack, including the route's callable + * and captures the resultant HTTP response object. It then sends the response + * back to the Application. + * + * @param ServerRequestInterface $request + * @param ResponseInterface $response + * + * @return ResponseInterface + */ + public function run(ServerRequestInterface $request, ResponseInterface $response) + { + // Finalise route now that we are about to run it + $this->finalize(); + + // Traverse middleware stack and fetch updated response + return $this->callMiddlewareStack($request, $response); + } + + /** + * Dispatch route callable against current Request and Response objects + * + * This method invokes the route object's callable. If middleware is + * registered for the route, each callable middleware is invoked in + * the order specified. + * + * @param ServerRequestInterface $request The current Request object + * @param ResponseInterface $response The current Response object + * @return \Psr\Http\Message\ResponseInterface + * @throws \Exception if the route callable throws an exception + */ + public function __invoke(ServerRequestInterface $request, ResponseInterface $response) + { + $this->callable = $this->resolveCallable($this->callable); + + /** @var InvocationStrategyInterface $handler */ + $handler = isset($this->container) ? $this->container->get('foundHandler') : new RequestResponse(); + + // invoke route callable + if ($this->outputBuffering === false) { + $newResponse = $handler($this->callable, $request, $response, $this->arguments); + } else { + try { + ob_start(); + $newResponse = $handler($this->callable, $request, $response, $this->arguments); + $output = ob_get_clean(); + } catch (Exception $e) { + ob_end_clean(); + throw $e; + } + } + + if ($newResponse instanceof ResponseInterface) { + // if route callback returns a ResponseInterface, then use it + $response = $newResponse; + } elseif (is_string($newResponse)) { + // if route callback returns a string, then append it to the response + if ($response->getBody()->isWritable()) { + $response->getBody()->write($newResponse); + } + } + + if (!empty($output) && $response->getBody()->isWritable()) { + if ($this->outputBuffering === 'prepend') { + // prepend output buffer content + $body = new Http\Body(fopen('php://temp', 'r+')); + $body->write($output . $response->getBody()); + $response = $response->withBody($body); + } elseif ($this->outputBuffering === 'append') { + // append output buffer content + $response->getBody()->write($output); + } + } + + return $response; + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/RouteGroup.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/RouteGroup.php new file mode 100644 index 000000000000..a0cdf4d47d8d --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/RouteGroup.php @@ -0,0 +1,47 @@ +pattern = $pattern; + $this->callable = $callable; + } + + /** + * Invoke the group to register any Routable objects within it. + * + * @param App $app The App to bind the callable to. + */ + public function __invoke(App $app = null) + { + $callable = $this->resolveCallable($this->callable); + if ($callable instanceof Closure && $app !== null) { + $callable = $callable->bindTo($app); + } + + $callable(); + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Router.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Router.php new file mode 100644 index 000000000000..b9d5d132ab2f --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/Slim/Router.php @@ -0,0 +1,421 @@ +routeParser = $parser ?: new StdParser; + } + + /** + * Set the base path used in pathFor() + * + * @param string $basePath + * + * @return self + */ + public function setBasePath($basePath) + { + if (!is_string($basePath)) { + throw new InvalidArgumentException('Router basePath must be a string'); + } + + $this->basePath = $basePath; + + return $this; + } + + /** + * Set path to fast route cache file. If this is false then route caching is disabled. + * + * @param string|false $cacheFile + * + * @return self + */ + public function setCacheFile($cacheFile) + { + if (!is_string($cacheFile) && $cacheFile !== false) { + throw new InvalidArgumentException('Router cacheFile must be a string or false'); + } + + $this->cacheFile = $cacheFile; + + if ($cacheFile !== false && !is_writable(dirname($cacheFile))) { + throw new RuntimeException('Router cacheFile directory must be writable'); + } + + + return $this; + } + + /** + * Add route + * + * @param string[] $methods Array of HTTP methods + * @param string $pattern The route pattern + * @param callable $handler The route callable + * + * @return RouteInterface + * + * @throws InvalidArgumentException if the route pattern isn't a string + */ + public function map($methods, $pattern, $handler) + { + if (!is_string($pattern)) { + throw new InvalidArgumentException('Route pattern must be a string'); + } + + // Prepend parent group pattern(s) + if ($this->routeGroups) { + $pattern = $this->processGroups() . $pattern; + } + + // According to RFC methods are defined in uppercase (See RFC 7231) + $methods = array_map("strtoupper", $methods); + + // Add route + $route = new Route($methods, $pattern, $handler, $this->routeGroups, $this->routeCounter); + $this->routes[$route->getIdentifier()] = $route; + $this->routeCounter++; + + return $route; + } + + /** + * Dispatch router for HTTP request + * + * @param ServerRequestInterface $request The current HTTP request object + * + * @return array + * + * @link https://github.com/nikic/FastRoute/blob/master/src/Dispatcher.php + */ + public function dispatch(ServerRequestInterface $request) + { + $uri = '/' . ltrim($request->getUri()->getPath(), '/'); + + return $this->createDispatcher()->dispatch( + $request->getMethod(), + $uri + ); + } + + /** + * @return \FastRoute\Dispatcher + */ + protected function createDispatcher() + { + if ($this->dispatcher) { + return $this->dispatcher; + } + + $routeDefinitionCallback = function (RouteCollector $r) { + foreach ($this->getRoutes() as $route) { + $r->addRoute($route->getMethods(), $route->getPattern(), $route->getIdentifier()); + } + }; + + if ($this->cacheFile) { + $this->dispatcher = \FastRoute\cachedDispatcher($routeDefinitionCallback, [ + 'routeParser' => $this->routeParser, + 'cacheFile' => $this->cacheFile, + ]); + } else { + $this->dispatcher = \FastRoute\simpleDispatcher($routeDefinitionCallback, [ + 'routeParser' => $this->routeParser, + ]); + } + + return $this->dispatcher; + } + + /** + * @param \FastRoute\Dispatcher $dispatcher + */ + public function setDispatcher(Dispatcher $dispatcher) + { + $this->dispatcher = $dispatcher; + } + + /** + * Get route objects + * + * @return Route[] + */ + public function getRoutes() + { + return $this->routes; + } + + /** + * Get named route object + * + * @param string $name Route name + * + * @return Route + * + * @throws RuntimeException If named route does not exist + */ + public function getNamedRoute($name) + { + foreach ($this->routes as $route) { + if ($name == $route->getName()) { + return $route; + } + } + throw new RuntimeException('Named route does not exist for name: ' . $name); + } + + /** + * Remove named route + * + * @param string $name Route name + * + * @throws RuntimeException If named route does not exist + */ + public function removeNamedRoute($name) + { + $route = $this->getNamedRoute($name); + + // no exception, route exists, now remove by id + unset($this->routes[$route->getIdentifier()]); + } + + /** + * Process route groups + * + * @return string A group pattern to prefix routes with + */ + protected function processGroups() + { + $pattern = ""; + foreach ($this->routeGroups as $group) { + $pattern .= $group->getPattern(); + } + return $pattern; + } + + /** + * Add a route group to the array + * + * @param string $pattern + * @param callable $callable + * + * @return RouteGroupInterface + */ + public function pushGroup($pattern, $callable) + { + $group = new RouteGroup($pattern, $callable); + array_push($this->routeGroups, $group); + return $group; + } + + /** + * Removes the last route group from the array + * + * @return RouteGroup|bool The RouteGroup if successful, else False + */ + public function popGroup() + { + $group = array_pop($this->routeGroups); + return $group instanceof RouteGroup ? $group : false; + } + + /** + * @param $identifier + * @return \Slim\Interfaces\RouteInterface + */ + public function lookupRoute($identifier) + { + if (!isset($this->routes[$identifier])) { + throw new RuntimeException('Route not found, looks like your route cache is stale.'); + } + return $this->routes[$identifier]; + } + + /** + * Build the path for a named route excluding the base path + * + * @param string $name Route name + * @param array $data Named argument replacement data + * @param array $queryParams Optional query string parameters + * + * @return string + * + * @throws RuntimeException If named route does not exist + * @throws InvalidArgumentException If required data not provided + */ + public function relativePathFor($name, array $data = [], array $queryParams = []) + { + $route = $this->getNamedRoute($name); + $pattern = $route->getPattern(); + + $routeDatas = $this->routeParser->parse($pattern); + // $routeDatas is an array of all possible routes that can be made. There is + // one routedata for each optional parameter plus one for no optional parameters. + // + // The most specific is last, so we look for that first. + $routeDatas = array_reverse($routeDatas); + + $segments = []; + foreach ($routeDatas as $routeData) { + foreach ($routeData as $item) { + if (is_string($item)) { + // this segment is a static string + $segments[] = $item; + continue; + } + + // This segment has a parameter: first element is the name + if (!array_key_exists($item[0], $data)) { + // we don't have a data element for this segment: cancel + // testing this routeData item, so that we can try a less + // specific routeData item. + $segments = []; + $segmentName = $item[0]; + break; + } + $segments[] = $data[$item[0]]; + } + if (!empty($segments)) { + // we found all the parameters for this route data, no need to check + // less specific ones + break; + } + } + + if (empty($segments)) { + throw new InvalidArgumentException('Missing data for URL segment: ' . $segmentName); + } + $url = implode('', $segments); + + if ($queryParams) { + $url .= '?' . http_build_query($queryParams); + } + + return $url; + } + + + /** + * Build the path for a named route including the base path + * + * @param string $name Route name + * @param array $data Named argument replacement data + * @param array $queryParams Optional query string parameters + * + * @return string + * + * @throws RuntimeException If named route does not exist + * @throws InvalidArgumentException If required data not provided + */ + public function pathFor($name, array $data = [], array $queryParams = []) + { + $url = $this->relativePathFor($name, $data, $queryParams); + + if ($this->basePath) { + $url = $this->basePath . $url; + } + + return $url; + } + + /** + * Build the path for a named route. + * + * This method is deprecated. Use pathFor() from now on. + * + * @param string $name Route name + * @param array $data Named argument replacement data + * @param array $queryParams Optional query string parameters + * + * @return string + * + * @throws RuntimeException If named route does not exist + * @throws InvalidArgumentException If required data not provided + */ + public function urlFor($name, array $data = [], array $queryParams = []) + { + trigger_error('urlFor() is deprecated. Use pathFor() instead.', E_USER_DEPRECATED); + return $this->pathFor($name, $data, $queryParams); + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/composer.json b/samples/server/petstore-security-test/slim/vendor/slim/slim/composer.json new file mode 100644 index 000000000000..808eb9d38577 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/composer.json @@ -0,0 +1,57 @@ +{ + "name": "slim/slim", + "type": "library", + "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", + "keywords": ["framework","micro","api","router"], + "homepage": "http://slimframework.com", + "license": "MIT", + "authors": [ + { + "name": "Josh Lockhart", + "email": "hello@joshlockhart.com", + "homepage": "https://joshlockhart.com" + }, + { + "name": "Andrew Smith", + "email": "a.smith@silentworks.co.uk", + "homepage": "http://silentworks.co.uk" + }, + { + "name": "Rob Allen", + "email": "rob@akrabat.com", + "homepage": "http://akrabat.com" + }, + { + "name": "Gabriel Manricks", + "email": "gmanricks@me.com", + "homepage": "http://gabrielmanricks.com" + } + ], + "require": { + "php": ">=5.5.0", + "pimple/pimple": "^3.0", + "psr/http-message": "^1.0", + "nikic/fast-route": "^1.0", + "container-interop/container-interop": "^1.1" + }, + "require-dev": { + "squizlabs/php_codesniffer": "^2.5", + "phpunit/phpunit": "^4.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "autoload": { + "psr-4": { + "Slim\\": "Slim" + } + }, + "scripts": { + "test": [ + "@phpunit", + "@phpcs" + ], + "phpunit": "php vendor/bin/phpunit", + "phpcs": "php vendor/bin/phpcs" + } +} diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/example/.htaccess b/samples/server/petstore-security-test/slim/vendor/slim/slim/example/.htaccess new file mode 100644 index 000000000000..0784bd22014a --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/example/.htaccess @@ -0,0 +1,12 @@ +# Note: see https://httpd.apache.org/docs/current/howto/htaccess.html: +# +# "You should avoid using .htaccess files completely if you have access to +# httpd main server config file. Using .htaccess files slows down your Apache +# http server. Any directive that you can include in a .htaccess file is +# better set in a Directory block, as it will have the same effect with +# better performance." + +RewriteEngine On +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule ^ index.php [QSA,L] diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/example/README.md b/samples/server/petstore-security-test/slim/vendor/slim/slim/example/README.md new file mode 100644 index 000000000000..e4fb35982c25 --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/example/README.md @@ -0,0 +1,19 @@ +# Slim example + +1. Install composer + + ```text + $ cd Slim + $ composer install + ``` + +2. Run php server + + ```text + $ cd Slim + $ php -S localhost:8888 -t example example/index.php + ``` + +3. Open browser + + Open http://localhost:8888 in your browser and you will see 'Welcome to Slim!' diff --git a/samples/server/petstore-security-test/slim/vendor/slim/slim/example/index.php b/samples/server/petstore-security-test/slim/vendor/slim/slim/example/index.php new file mode 100644 index 000000000000..ef895f83f93b --- /dev/null +++ b/samples/server/petstore-security-test/slim/vendor/slim/slim/example/index.php @@ -0,0 +1,45 @@ +get('/', function ($request, $response, $args) { + $response->write("Welcome to Slim!"); + return $response; +}); + +$app->get('/hello[/{name}]', function ($request, $response, $args) { + $response->write("Hello, " . $args['name']); + return $response; +})->setArgument('name', 'World!'); + +/** + * Step 4: Run the Slim application + * + * This method should be called last. This executes the Slim application + * and returns the HTTP response to the HTTP client. + */ +$app->run(); diff --git a/samples/server/petstore/slim/SwaggerServer/.htaccess b/samples/server/petstore/slim/.htaccess similarity index 100% rename from samples/server/petstore/slim/SwaggerServer/.htaccess rename to samples/server/petstore/slim/.htaccess diff --git a/samples/server/petstore/slim/LICENSE b/samples/server/petstore/slim/LICENSE index d9a10c0d8e86..8dada3edaf50 100644 --- a/samples/server/petstore/slim/LICENSE +++ b/samples/server/petstore/slim/LICENSE @@ -174,3 +174,28 @@ of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/samples/server/petstore/slim/SwaggerServer/README.md b/samples/server/petstore/slim/README.md similarity index 100% rename from samples/server/petstore/slim/SwaggerServer/README.md rename to samples/server/petstore/slim/README.md diff --git a/samples/server/petstore/slim/SwaggerServer/composer.json b/samples/server/petstore/slim/composer.json similarity index 100% rename from samples/server/petstore/slim/SwaggerServer/composer.json rename to samples/server/petstore/slim/composer.json diff --git a/samples/server/petstore/slim/composer.lock b/samples/server/petstore/slim/composer.lock new file mode 100644 index 000000000000..3007790bbebd --- /dev/null +++ b/samples/server/petstore/slim/composer.lock @@ -0,0 +1,254 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "834a8ce57aaea28f119aedff36481779", + "content-hash": "913417690829da41975a473b88f30f64", + "packages": [ + { + "name": "container-interop/container-interop", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/container-interop/container-interop.git", + "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/container-interop/container-interop/zipball/fc08354828f8fd3245f77a66b9e23a6bca48297e", + "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Interop\\Container\\": "src/Interop/Container/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", + "time": "2014-12-30 15:22:37" + }, + { + "name": "nikic/fast-route", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/nikic/FastRoute.git", + "reference": "8ea928195fa9b907f0d6e48312d323c1a13cc2af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/FastRoute/zipball/8ea928195fa9b907f0d6e48312d323c1a13cc2af", + "reference": "8ea928195fa9b907f0d6e48312d323c1a13cc2af", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "FastRoute\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "description": "Fast request router for PHP", + "keywords": [ + "router", + "routing" + ], + "time": "2016-06-12 19:08:51" + }, + { + "name": "pimple/pimple", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/silexphp/Pimple.git", + "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a30f7d6e57565a2e1a316e1baf2a483f788b258a", + "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Pimple": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Pimple, a simple Dependency Injection Container", + "homepage": "http://pimple.sensiolabs.org", + "keywords": [ + "container", + "dependency injection" + ], + "time": "2015-09-11 15:10:35" + }, + { + "name": "psr/http-message", + "version": "1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2015-05-04 20:22:00" + }, + { + "name": "slim/slim", + "version": "3.4.2", + "source": { + "type": "git", + "url": "https://github.com/slimphp/Slim.git", + "reference": "a132385f736063d00632b52b3f8a389fe66fe4fa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slimphp/Slim/zipball/a132385f736063d00632b52b3f8a389fe66fe4fa", + "reference": "a132385f736063d00632b52b3f8a389fe66fe4fa", + "shasum": "" + }, + "require": { + "container-interop/container-interop": "^1.1", + "nikic/fast-route": "^1.0", + "php": ">=5.5.0", + "pimple/pimple": "^3.0", + "psr/http-message": "^1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0", + "squizlabs/php_codesniffer": "^2.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Slim\\": "Slim" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rob Allen", + "email": "rob@akrabat.com", + "homepage": "http://akrabat.com" + }, + { + "name": "Josh Lockhart", + "email": "hello@joshlockhart.com", + "homepage": "https://joshlockhart.com" + }, + { + "name": "Gabriel Manricks", + "email": "gmanricks@me.com", + "homepage": "http://gabrielmanricks.com" + }, + { + "name": "Andrew Smith", + "email": "a.smith@silentworks.co.uk", + "homepage": "http://silentworks.co.uk" + } + ], + "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", + "homepage": "http://slimframework.com", + "keywords": [ + "api", + "framework", + "micro", + "router" + ], + "time": "2016-05-25 11:23:38" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "RC", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/samples/server/petstore/slim/SwaggerServer/index.php b/samples/server/petstore/slim/index.php similarity index 100% rename from samples/server/petstore/slim/SwaggerServer/index.php rename to samples/server/petstore/slim/index.php diff --git a/samples/server/petstore/slim/lib/Models/ApiResponse.php b/samples/server/petstore/slim/lib/Models/ApiResponse.php new file mode 100644 index 000000000000..dae8eb24117c --- /dev/null +++ b/samples/server/petstore/slim/lib/Models/ApiResponse.php @@ -0,0 +1,17 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see http://www.php-fig.org/psr/psr-0/ + * @see http://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + + private $classMapAuthoritative = false; + + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + return array(); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 + if ('\\' == $class[0]) { + $class = substr($class, 1); + } + + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative) { + return false; + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if ($file === null && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if ($file === null) { + // Remember that this class does not exist. + return $this->classMap[$class] = false; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { + if (0 === strpos($class, $prefix)) { + foreach ($this->prefixDirsPsr4[$prefix] as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/samples/server/petstore/slim/vendor/composer/LICENSE b/samples/server/petstore/slim/vendor/composer/LICENSE new file mode 100644 index 000000000000..1a28124886db --- /dev/null +++ b/samples/server/petstore/slim/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) 2016 Nils Adermann, Jordi Boggiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/samples/server/petstore/slim/vendor/composer/autoload_classmap.php b/samples/server/petstore/slim/vendor/composer/autoload_classmap.php new file mode 100644 index 000000000000..7a91153b0d8e --- /dev/null +++ b/samples/server/petstore/slim/vendor/composer/autoload_classmap.php @@ -0,0 +1,9 @@ + $vendorDir . '/nikic/fast-route/src/functions.php', +); diff --git a/samples/server/petstore/slim/vendor/composer/autoload_namespaces.php b/samples/server/petstore/slim/vendor/composer/autoload_namespaces.php new file mode 100644 index 000000000000..c3cd02297dec --- /dev/null +++ b/samples/server/petstore/slim/vendor/composer/autoload_namespaces.php @@ -0,0 +1,10 @@ + array($vendorDir . '/pimple/pimple/src'), +); diff --git a/samples/server/petstore/slim/vendor/composer/autoload_psr4.php b/samples/server/petstore/slim/vendor/composer/autoload_psr4.php new file mode 100644 index 000000000000..7e403d2e2d0f --- /dev/null +++ b/samples/server/petstore/slim/vendor/composer/autoload_psr4.php @@ -0,0 +1,13 @@ + array($vendorDir . '/slim/slim/Slim'), + 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'), + 'Interop\\Container\\' => array($vendorDir . '/container-interop/container-interop/src/Interop/Container'), + 'FastRoute\\' => array($vendorDir . '/nikic/fast-route/src'), +); diff --git a/samples/server/petstore/slim/vendor/composer/autoload_real.php b/samples/server/petstore/slim/vendor/composer/autoload_real.php new file mode 100644 index 000000000000..8911c4b258f5 --- /dev/null +++ b/samples/server/petstore/slim/vendor/composer/autoload_real.php @@ -0,0 +1,59 @@ + $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + + $loader->register(true); + + $includeFiles = require __DIR__ . '/autoload_files.php'; + foreach ($includeFiles as $fileIdentifier => $file) { + composerRequire8ad75658dadd8f07df6a5456dd736c25($fileIdentifier, $file); + } + + return $loader; + } +} + +function composerRequire8ad75658dadd8f07df6a5456dd736c25($fileIdentifier, $file) +{ + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + require $file; + + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + } +} diff --git a/samples/server/petstore/slim/vendor/composer/installed.json b/samples/server/petstore/slim/vendor/composer/installed.json new file mode 100644 index 000000000000..9e041100fe23 --- /dev/null +++ b/samples/server/petstore/slim/vendor/composer/installed.json @@ -0,0 +1,247 @@ +[ + { + "name": "container-interop/container-interop", + "version": "1.1.0", + "version_normalized": "1.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/container-interop/container-interop.git", + "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/container-interop/container-interop/zipball/fc08354828f8fd3245f77a66b9e23a6bca48297e", + "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e", + "shasum": "" + }, + "time": "2014-12-30 15:22:37", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Interop\\Container\\": "src/Interop/Container/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Promoting the interoperability of container objects (DIC, SL, etc.)" + }, + { + "name": "nikic/fast-route", + "version": "v1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/FastRoute.git", + "reference": "8ea928195fa9b907f0d6e48312d323c1a13cc2af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/FastRoute/zipball/8ea928195fa9b907f0d6e48312d323c1a13cc2af", + "reference": "8ea928195fa9b907f0d6e48312d323c1a13cc2af", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "time": "2016-06-12 19:08:51", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "FastRoute\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "description": "Fast request router for PHP", + "keywords": [ + "router", + "routing" + ] + }, + { + "name": "psr/http-message", + "version": "1.0", + "version_normalized": "1.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2015-05-04 20:22:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ] + }, + { + "name": "pimple/pimple", + "version": "v3.0.2", + "version_normalized": "3.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/silexphp/Pimple.git", + "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a30f7d6e57565a2e1a316e1baf2a483f788b258a", + "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2015-09-11 15:10:35", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Pimple": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Pimple, a simple Dependency Injection Container", + "homepage": "http://pimple.sensiolabs.org", + "keywords": [ + "container", + "dependency injection" + ] + }, + { + "name": "slim/slim", + "version": "3.4.2", + "version_normalized": "3.4.2.0", + "source": { + "type": "git", + "url": "https://github.com/slimphp/Slim.git", + "reference": "a132385f736063d00632b52b3f8a389fe66fe4fa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slimphp/Slim/zipball/a132385f736063d00632b52b3f8a389fe66fe4fa", + "reference": "a132385f736063d00632b52b3f8a389fe66fe4fa", + "shasum": "" + }, + "require": { + "container-interop/container-interop": "^1.1", + "nikic/fast-route": "^1.0", + "php": ">=5.5.0", + "pimple/pimple": "^3.0", + "psr/http-message": "^1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0", + "squizlabs/php_codesniffer": "^2.5" + }, + "time": "2016-05-25 11:23:38", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Slim\\": "Slim" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rob Allen", + "email": "rob@akrabat.com", + "homepage": "http://akrabat.com" + }, + { + "name": "Josh Lockhart", + "email": "hello@joshlockhart.com", + "homepage": "https://joshlockhart.com" + }, + { + "name": "Gabriel Manricks", + "email": "gmanricks@me.com", + "homepage": "http://gabrielmanricks.com" + }, + { + "name": "Andrew Smith", + "email": "a.smith@silentworks.co.uk", + "homepage": "http://silentworks.co.uk" + } + ], + "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", + "homepage": "http://slimframework.com", + "keywords": [ + "api", + "framework", + "micro", + "router" + ] + } +] diff --git a/samples/server/petstore/slim/vendor/container-interop/container-interop/.gitignore b/samples/server/petstore/slim/vendor/container-interop/container-interop/.gitignore new file mode 100644 index 000000000000..b2395aa05541 --- /dev/null +++ b/samples/server/petstore/slim/vendor/container-interop/container-interop/.gitignore @@ -0,0 +1,3 @@ +composer.lock +composer.phar +/vendor/ diff --git a/samples/server/petstore/slim/vendor/container-interop/container-interop/LICENSE b/samples/server/petstore/slim/vendor/container-interop/container-interop/LICENSE new file mode 100644 index 000000000000..7671d9020f64 --- /dev/null +++ b/samples/server/petstore/slim/vendor/container-interop/container-interop/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 container-interop + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/samples/server/petstore/slim/vendor/container-interop/container-interop/README.md b/samples/server/petstore/slim/vendor/container-interop/container-interop/README.md new file mode 100644 index 000000000000..ec434d0f2683 --- /dev/null +++ b/samples/server/petstore/slim/vendor/container-interop/container-interop/README.md @@ -0,0 +1,85 @@ +# Container Interoperability + +[![Latest Stable Version](https://poser.pugx.org/container-interop/container-interop/v/stable.png)](https://packagist.org/packages/container-interop/container-interop) + +*container-interop* tries to identify and standardize features in *container* objects (service locators, +dependency injection containers, etc.) to achieve interopererability. + +Through discussions and trials, we try to create a standard, made of common interfaces but also recommendations. + +If PHP projects that provide container implementations begin to adopt these common standards, then PHP +applications and projects that use containers can depend on the common interfaces instead of specific +implementations. This facilitates a high-level of interoperability and flexibility that allows users to consume +*any* container implementation that can be adapted to these interfaces. + +The work done in this project is not officially endorsed by the [PHP-FIG](http://www.php-fig.org/), but it is being +worked on by members of PHP-FIG and other good developers. We adhere to the spirit and ideals of PHP-FIG, and hope +this project will pave the way for one or more future PSRs. + + +## Installation + +You can install this package through Composer: + +```json +{ + "require": { + "container-interop/container-interop": "~1.0" + } +} +``` + +The packages adheres to the [SemVer](http://semver.org/) specification, and there will be full backward compatibility +between minor versions. + +## Standards + +### Available + +- [`ContainerInterface`](src/Interop/Container/ContainerInterface.php). +[Description](docs/ContainerInterface.md) [Meta Document](docs/ContainerInterface-meta.md). +Describes the interface of a container that exposes methods to read its entries. +- [*Delegate lookup feature*](docs/Delegate-lookup.md). +[Meta Document](docs/Delegate-lookup-meta.md). +Describes the ability for a container to delegate the lookup of its dependencies to a third-party container. This +feature lets several containers work together in a single application. + +### Proposed + +View open [request for comments](https://github.com/container-interop/container-interop/labels/RFC) + +## Compatible projects + +### Projects implementing `ContainerInterface` + +- [Acclimate](https://github.com/jeremeamia/acclimate-container) +- [dcp-di](https://github.com/estelsmith/dcp-di) +- [Mouf](http://mouf-php.com) +- [Njasm Container](https://github.com/njasm/container) +- [PHP-DI](http://php-di.org) +- [PimpleInterop](https://github.com/moufmouf/pimple-interop) +- [XStatic](https://github.com/jeremeamia/xstatic) + +### Projects implementing the *delegate lookup* feature + +- [Mouf](http://mouf-php.com) +- [PHP-DI](http://php-di.org) +- [PimpleInterop](https://github.com/moufmouf/pimple-interop) + +## Workflow + +Everyone is welcome to join and contribute. + +The general workflow looks like this: + +1. Someone opens a discussion (GitHub issue) to suggest an interface +1. Feedback is gathered +1. The interface is added to a development branch +1. We release alpha versions so that the interface can be experimented with +1. Discussions and edits ensue until the interface is deemed stable by a general consensus +1. A new minor version of the package is released + +We try to not break BC by creating new interfaces instead of editing existing ones. + +While we currently work on interfaces, we are open to anything that might help towards interoperability, may that +be code, best practices, etc. diff --git a/samples/server/petstore/slim/vendor/container-interop/container-interop/composer.json b/samples/server/petstore/slim/vendor/container-interop/container-interop/composer.json new file mode 100644 index 000000000000..84f38752822f --- /dev/null +++ b/samples/server/petstore/slim/vendor/container-interop/container-interop/composer.json @@ -0,0 +1,11 @@ +{ + "name": "container-interop/container-interop", + "type": "library", + "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", + "license": "MIT", + "autoload": { + "psr-4": { + "Interop\\Container\\": "src/Interop/Container/" + } + } +} diff --git a/samples/server/petstore/slim/vendor/container-interop/container-interop/docs/ContainerInterface-meta.md b/samples/server/petstore/slim/vendor/container-interop/container-interop/docs/ContainerInterface-meta.md new file mode 100644 index 000000000000..90711c9051d2 --- /dev/null +++ b/samples/server/petstore/slim/vendor/container-interop/container-interop/docs/ContainerInterface-meta.md @@ -0,0 +1,114 @@ +# ContainerInterface Meta Document + +## Introduction + +This document describes the process and discussions that lead to the `ContainerInterface`. +Its goal is to explain the reasons behind each decision. + +## Goal + +The goal set by `ContainerInterface` is to standardize how frameworks and libraries make use of a +container to obtain objects and parameters. + +By standardizing such a behavior, frameworks and libraries using the `ContainerInterface` +could work with any compatible container. +That would allow end users to choose their own container based on their own preferences. + +It is important to distinguish the two usages of a container: + +- configuring entries +- fetching entries + +Most of the time, those two sides are not used by the same party. +While it is often end users who tend to configure entries, it is generally the framework that fetch +entries to build the application. + +This is why this interface focuses only on how entries can be fetched from a container. + +## Interface name + +The interface name has been thoroughly discussed and was decided by a vote. + +The list of options considered with their respective votes are: + +- `ContainerInterface`: +8 +- `ProviderInterface`: +2 +- `LocatorInterface`: 0 +- `ReadableContainerInterface`: -5 +- `ServiceLocatorInterface`: -6 +- `ObjectFactory`: -6 +- `ObjectStore`: -8 +- `ConsumerInterface`: -9 + +[Full results of the vote](https://github.com/container-interop/container-interop/wiki/%231-interface-name:-Vote) + +The complete discussion can be read in [the issue #1](https://github.com/container-interop/container-interop/issues/1). + +## Interface methods + +The choice of which methods the interface would contain was made after a statistical analysis of existing containers. +The results of this analysis are available [in this document](https://gist.github.com/mnapoli/6159681). + +The summary of the analysis showed that: + +- all containers offer a method to get an entry by its id +- a large majority name such method `get()` +- for all containers, the `get()` method has 1 mandatory parameter of type string +- some containers have an optional additional argument for `get()`, but it doesn't same the same purpose between containers +- a large majority of the containers offer a method to test if it can return an entry by its id +- a majority name such method `has()` +- for all containers offering `has()`, the method has exactly 1 parameter of type string +- a large majority of the containers throw an exception rather than returning null when an entry is not found in `get()` +- a large majority of the containers don't implement `ArrayAccess` + +The question of whether to include methods to define entries has been discussed in +[issue #1](https://github.com/container-interop/container-interop/issues/1). +It has been judged that such methods do not belong in the interface described here because it is out of its scope +(see the "Goal" section). + +As a result, the `ContainerInterface` contains two methods: + +- `get()`, returning anything, with one mandatory string parameter. Should throw an exception if the entry is not found. +- `has()`, returning a boolean, with one mandatory string parameter. + +### Number of parameters in `get()` method + +While `ContainerInterface` only defines one mandatory parameter in `get()`, it is not incompatible with +existing containers that have additional optional parameters. PHP allows an implementation to offer more parameters +as long as they are optional, because the implementation *does* satisfy the interface. + +This issue has been discussed in [issue #6](https://github.com/container-interop/container-interop/issues/6). + +### Type of the `$id` parameter + +The type of the `$id` parameter in `get()` and `has()` has been discussed in +[issue #6](https://github.com/container-interop/container-interop/issues/6). +While `string` is used in all the containers that were analyzed, it was suggested that allowing +anything (such as objects) could allow containers to offer a more advanced query API. + +An example given was to use the container as an object builder. The `$id` parameter would then be an +object that would describe how to create an instance. + +The conclusion of the discussion was that this was beyond the scope of getting entries from a container without +knowing how the container provided them, and it was more fit for a factory. + +## Contributors + +Are listed here all people that contributed in the discussions or votes, by alphabetical order: + +- [Amy Stephen](https://github.com/AmyStephen) +- [David Négrier](https://github.com/moufmouf) +- [Don Gilbert](https://github.com/dongilbert) +- [Jason Judge](https://github.com/judgej) +- [Jeremy Lindblom](https://github.com/jeremeamia) +- [Marco Pivetta](https://github.com/Ocramius) +- [Matthieu Napoli](https://github.com/mnapoli) +- [Paul M. Jones](https://github.com/pmjones) +- [Stephan Hochdörfer](https://github.com/shochdoerfer) +- [Taylor Otwell](https://github.com/taylorotwell) + +## Relevant links + +- [`ContainerInterface.php`](https://github.com/container-interop/container-interop/blob/master/src/Interop/Container/ContainerInterface.php) +- [List of all issues](https://github.com/container-interop/container-interop/issues?labels=ContainerInterface&milestone=&page=1&state=closed) +- [Vote for the interface name](https://github.com/container-interop/container-interop/wiki/%231-interface-name:-Vote) diff --git a/samples/server/petstore/slim/vendor/container-interop/container-interop/docs/ContainerInterface.md b/samples/server/petstore/slim/vendor/container-interop/container-interop/docs/ContainerInterface.md new file mode 100644 index 000000000000..9f609674c801 --- /dev/null +++ b/samples/server/petstore/slim/vendor/container-interop/container-interop/docs/ContainerInterface.md @@ -0,0 +1,153 @@ +Container interface +=================== + +This document describes a common interface for dependency injection containers. + +The goal set by `ContainerInterface` is to standardize how frameworks and libraries make use of a +container to obtain objects and parameters (called *entries* in the rest of this document). + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", +"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be +interpreted as described in [RFC 2119][]. + +The word `implementor` in this document is to be interpreted as someone +implementing the `ContainerInterface` in a depency injection-related library or framework. +Users of dependency injections containers (DIC) are refered to as `user`. + +[RFC 2119]: http://tools.ietf.org/html/rfc2119 + +1. Specification +----------------- + +### 1.1 Basics + +- The `Interop\Container\ContainerInterface` exposes two methods : `get` and `has`. + +- `get` takes one mandatory parameter: an entry identifier. It MUST be a string. + A call to `get` can return anything (a *mixed* value), or throws an exception if the identifier + is not known to the container. Two successive calls to `get` with the same + identifier SHOULD return the same value. However, depending on the `implementor` + design and/or `user` configuration, different values might be returned, so + `user` SHOULD NOT rely on getting the same value on 2 successive calls. + While `ContainerInterface` only defines one mandatory parameter in `get()`, implementations + MAY accept additional optional parameters. + +- `has` takes one unique parameter: an entry identifier. It MUST return `true` + if an entry identifier is known to the container and `false` if it is not. + +### 1.2 Exceptions + +Exceptions directly thrown by the container MUST implement the +[`Interop\Container\Exception\ContainerException`](../src/Interop/Container/Exception/ContainerException.php). + +A call to the `get` method with a non-existing id should throw a +[`Interop\Container\Exception\NotFoundException`](../src/Interop/Container/Exception/NotFoundException.php). + +### 1.3 Additional features + +This section describes additional features that MAY be added to a container. Containers are not +required to implement these features to respect the ContainerInterface. + +#### 1.3.1 Delegate lookup feature + +The goal of the *delegate lookup* feature is to allow several containers to share entries. +Containers implementing this feature can perform dependency lookups in other containers. + +Containers implementing this feature will offer a greater lever of interoperability +with other containers. Implementation of this feature is therefore RECOMMENDED. + +A container implementing this feature: + +- MUST implement the `ContainerInterface` +- MUST provide a way to register a delegate container (using a constructor parameter, or a setter, + or any possible way). The delegate container MUST implement the `ContainerInterface`. + +When a container is configured to use a delegate container for dependencies: + +- Calls to the `get` method should only return an entry if the entry is part of the container. + If the entry is not part of the container, an exception should be thrown + (as requested by the `ContainerInterface`). +- Calls to the `has` method should only return `true` if the entry is part of the container. + If the entry is not part of the container, `false` should be returned. +- If the fetched entry has dependencies, **instead** of performing + the dependency lookup in the container, the lookup is performed on the *delegate container*. + +Important! By default, the lookup SHOULD be performed on the delegate container **only**, not on the container itself. + +It is however allowed for containers to provide exception cases for special entries, and a way to lookup +into the same container (or another container) instead of the delegate container. + +2. Package +---------- + +The interfaces and classes described as well as relevant exception are provided as part of the +[container-interop/container-interop](https://packagist.org/packages/container-interop/container-interop) package. + +3. `Interop\Container\ContainerInterface` +----------------------------------------- + +```php +setParentContainer($this); + } + } + ... + } +} + +``` + +**Cons:** + +Cons have been extensively discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51721777). +Basically, forcing a setter into an interface is a bad idea. Setters are similar to constructor arguments, +and it's a bad idea to standardize a constructor: how the delegate container is configured into a container is an implementation detail. This outweights the benefits of the interface. + +### 4.4 Alternative: no exception case for delegate lookups + +Originally, the proposed wording for delegate lookup calls was: + +> Important! The lookup MUST be performed on the delegate container **only**, not on the container itself. + +This was later replaced by: + +> Important! By default, the lookup SHOULD be performed on the delegate container **only**, not on the container itself. +> +> It is however allowed for containers to provide exception cases for special entries, and a way to lookup +> into the same container (or another container) instead of the delegate container. + +Exception cases have been allowed to avoid breaking dependencies with some services that must be provided +by the container (on @njasm proposal). This was proposed here: https://github.com/container-interop/container-interop/pull/20#issuecomment-56597235 + +### 4.5 Alternative: having one of the containers act as the composite container + +In real-life scenarios, we usually have a big framework (Symfony 2, Zend Framework 2, etc...) and we want to +add another DI container to this container. Most of the time, the "big" framework will be responsible for +creating the controller's instances, using it's own DI container. Until *container-interop* is fully adopted, +the "big" framework will not be aware of the existence of a composite container that it should use instead +of its own container. + +For this real-life use cases, @mnapoli and @moufmouf proposed to extend the "big" framework's DI container +to make it act as a composite container. + +This has been discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-40367194) +and [here](http://mouf-php.com/container-interop-whats-next#solution4). + +This was implemented in Symfony 2 using: + +- [interop.symfony.di](https://github.com/thecodingmachine/interop.symfony.di/tree/v0.1.0) +- [framework interop](https://github.com/mnapoli/framework-interop/) + +This was implemented in Silex using: + +- [interop.silex.di](https://github.com/thecodingmachine/interop.silex.di) + +Having a container act as the composite container is not part of the delegate lookup standard because it is +simply a temporary design pattern used to make existing frameworks that do not support yet ContainerInterop +play nice with other DI containers. + + +5. Implementations +------------------ + +The following projects already implement the delegate lookup feature: + +- [Mouf](http://mouf-php.com), through the [`setDelegateLookupContainer` method](https://github.com/thecodingmachine/mouf/blob/2.0/src/Mouf/MoufManager.php#L2120) +- [PHP-DI](http://php-di.org/), through the [`$wrapperContainer` parameter of the constructor](https://github.com/mnapoli/PHP-DI/blob/master/src/DI/Container.php#L72) +- [pimple-interop](https://github.com/moufmouf/pimple-interop), through the [`$container` parameter of the constructor](https://github.com/moufmouf/pimple-interop/blob/master/src/Interop/Container/Pimple/PimpleInterop.php#L62) + +6. People +--------- + +Are listed here all people that contributed in the discussions, by alphabetical order: + +- [Alexandru Pătrănescu](https://github.com/drealecs) +- [Ben Peachey](https://github.com/potherca) +- [David Négrier](https://github.com/moufmouf) +- [Jeremy Lindblom](https://github.com/jeremeamia) +- [Marco Pivetta](https://github.com/Ocramius) +- [Matthieu Napoli](https://github.com/mnapoli) +- [Nelson J Morais](https://github.com/njasm) +- [Phil Sturgeon](https://github.com/philsturgeon) +- [Stephan Hochdörfer](https://github.com/shochdoerfer) + +7. Relevant Links +----------------- + +_**Note:** Order descending chronologically._ + +- [Pull request on the delegate lookup feature](https://github.com/container-interop/container-interop/pull/20) +- [Pull request on the interface idea](https://github.com/container-interop/container-interop/pull/8) +- [Original article exposing the delegate lookup idea along many others](http://mouf-php.com/container-interop-whats-next) + diff --git a/samples/server/petstore/slim/vendor/container-interop/container-interop/docs/Delegate-lookup.md b/samples/server/petstore/slim/vendor/container-interop/container-interop/docs/Delegate-lookup.md new file mode 100644 index 000000000000..04eb3aea023d --- /dev/null +++ b/samples/server/petstore/slim/vendor/container-interop/container-interop/docs/Delegate-lookup.md @@ -0,0 +1,60 @@ +Delegate lookup feature +======================= + +This document describes a standard for dependency injection containers. + +The goal set by the *delegate lookup* feature is to allow several containers to share entries. +Containers implementing this feature can perform dependency lookups in other containers. + +Containers implementing this feature will offer a greater lever of interoperability +with other containers. Implementation of this feature is therefore RECOMMENDED. + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", +"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be +interpreted as described in [RFC 2119][]. + +The word `implementor` in this document is to be interpreted as someone +implementing the delegate lookup feature in a dependency injection-related library or framework. +Users of dependency injections containers (DIC) are refered to as `user`. + +[RFC 2119]: http://tools.ietf.org/html/rfc2119 + +1. Vocabulary +------------- + +In a dependency injection container, the container is used to fetch entries. +Entries can have dependencies on other entries. Usually, these other entries are fetched by the container. + +The *delegate lookup* feature is the ability for a container to fetch dependencies in +another container. In the rest of the document, the word "container" will reference the container +implemented by the implementor. The word "delegate container" will reference the container we are +fetching the dependencies from. + +2. Specification +---------------- + +A container implementing the *delegate lookup* feature: + +- MUST implement the [`ContainerInterface`](ContainerInterface.md) +- MUST provide a way to register a delegate container (using a constructor parameter, or a setter, + or any possible way). The delegate container MUST implement the [`ContainerInterface`](ContainerInterface.md). + +When a container is configured to use a delegate container for dependencies: + +- Calls to the `get` method should only return an entry if the entry is part of the container. + If the entry is not part of the container, an exception should be thrown + (as requested by the [`ContainerInterface`](ContainerInterface.md)). +- Calls to the `has` method should only return `true` if the entry is part of the container. + If the entry is not part of the container, `false` should be returned. +- If the fetched entry has dependencies, **instead** of performing + the dependency lookup in the container, the lookup is performed on the *delegate container*. + +Important: By default, the dependency lookups SHOULD be performed on the delegate container **only**, not on the container itself. + +It is however allowed for containers to provide exception cases for special entries, and a way to lookup +into the same container (or another container) instead of the delegate container. + +3. Package / Interface +---------------------- + +This feature is not tied to any code, interface or package. diff --git a/samples/server/petstore/slim/vendor/container-interop/container-interop/docs/images/interoperating_containers.png b/samples/server/petstore/slim/vendor/container-interop/container-interop/docs/images/interoperating_containers.png new file mode 100644 index 0000000000000000000000000000000000000000..9c672e16c72a08708ea5bdeb51757c2951d3ee66 GIT binary patch literal 35971 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 literal 0 HcmV?d00001 diff --git a/samples/server/petstore/slim/vendor/container-interop/container-interop/docs/images/priority.png b/samples/server/petstore/slim/vendor/container-interop/container-interop/docs/images/priority.png new file mode 100644 index 0000000000000000000000000000000000000000..5760dc71b557fea7ec5bd5699adfd1c228b9cdec GIT binary patch literal 22949 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 + } + + class RouteCollector { + public function __construct(RouteParser $routeParser, DataGenerator $dataGenerator); + public function addRoute(mixed $httpMethod, string $route, mixed $handler): void; + public function getData(): array; + } + + class Route { + public function __construct(string $httpMethod, mixed $handler, string $regex, array $variables); + public function matches(string $str): bool; + } + + interface DataGenerator { + public function addRoute(string $httpMethod, array $routeData, mixed $handler); + public function getData(): array; + } + + interface Dispatcher { + const int NOT_FOUND = 0; + const int FOUND = 1; + const int METHOD_NOT_ALLOWED = 2; + public function dispatch(string $httpMethod, string $uri): array; + } + + function simpleDispatcher( + (function(RouteCollector): void) $routeDefinitionCallback, + shape( + 'routeParser' => ?classname, + 'dataGenerator' => ?classname, + 'dispatcher' => ?classname, + 'routeCollector' => ?classname, + ) $options = shape()): Dispatcher; + + function cachedDispatcher( + (function(RouteCollector): void) $routeDefinitionCallback, + shape( + 'routeParser' => ?classname, + 'dataGenerator' => ?classname, + 'dispatcher' => ?classname, + 'routeCollector' => ?classname, + 'cacheDisabled' => ?bool, + 'cacheFile' => ?string, + ) $options = shape()): Dispatcher; +} + +namespace FastRoute\DataGenerator { + abstract class RegexBasedAbstract implements \FastRoute\DataGenerator { + protected abstract function getApproxChunkSize(); + protected abstract function processChunk($regexToRoutesMap); + + public function addRoute(string $httpMethod, array $routeData, mixed $handler): void; + public function getData(): array; + } + + class CharCountBased extends RegexBasedAbstract { + protected function getApproxChunkSize(): int; + protected function processChunk(array $regexToRoutesMap): array; + } + + class GroupCountBased extends RegexBasedAbstract { + protected function getApproxChunkSize(): int; + protected function processChunk(array $regexToRoutesMap): array; + } + + class GroupPosBased extends RegexBasedAbstract { + protected function getApproxChunkSize(): int; + protected function processChunk(array $regexToRoutesMap): array; + } + + class MarkBased extends RegexBasedAbstract { + protected function getApproxChunkSize(): int; + protected function processChunk(array $regexToRoutesMap): array; + } +} + +namespace FastRoute\Dispatcher { + abstract class RegexBasedAbstract implements \FastRoute\Dispatcher { + protected abstract function dispatchVariableRoute(array $routeData, string $uri): array; + + public function dispatch(string $httpMethod, string $uri): array; + } + + class GroupPosBased extends RegexBasedAbstract { + public function __construct(array $data); + protected function dispatchVariableRoute(array $routeData, string $uri): array; + } + + class GroupCountBased extends RegexBasedAbstract { + public function __construct(array $data); + protected function dispatchVariableRoute(array $routeData, string $uri): array; + } + + class CharCountBased extends RegexBasedAbstract { + public function __construct(array $data); + protected function dispatchVariableRoute(array $routeData, string $uri): array; + } + + class MarkBased extends RegexBasedAbstract { + public function __construct(array $data); + protected function dispatchVariableRoute(array $routeData, string $uri): array; + } +} + +namespace FastRoute\RouteParser { + class Std implements \FastRoute\RouteParser { + const string VARIABLE_REGEX = <<<'REGEX' +\{ + \s* ([a-zA-Z][a-zA-Z0-9_]*) \s* + (?: + : \s* ([^{}]*(?:\{(?-1)\}[^{}]*)*) + )? +\} +REGEX; + const string DEFAULT_DISPATCH_REGEX = '[^/]+'; + public function parse(string $route): array; + } +} diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/LICENSE b/samples/server/petstore/slim/vendor/nikic/fast-route/LICENSE new file mode 100644 index 000000000000..478e7641e93d --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/LICENSE @@ -0,0 +1,31 @@ +Copyright (c) 2013 by Nikita Popov. + +Some rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/README.md b/samples/server/petstore/slim/vendor/nikic/fast-route/README.md new file mode 100644 index 000000000000..f812a2a014ca --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/README.md @@ -0,0 +1,273 @@ +FastRoute - Fast request router for PHP +======================================= + +This library provides a fast implementation of a regular expression based router. [Blog post explaining how the +implementation works and why it is fast.][blog_post] + +Install +------- + +To install with composer: + +```sh +composer require nikic/fast-route +``` + +Requires PHP 5.4 or newer. + +Usage +----- + +Here's a basic usage example: + +```php +addRoute('GET', '/users', 'get_all_users_handler'); + // {id} must be a number (\d+) + $r->addRoute('GET', '/user/{id:\d+}', 'get_user_handler'); + // The /{title} suffix is optional + $r->addRoute('GET', '/articles/{id:\d+}[/{title}]', 'get_article_handler'); +}); + +// Fetch method and URI from somewhere +$httpMethod = $_SERVER['REQUEST_METHOD']; +$uri = $_SERVER['REQUEST_URI']; + +// Strip query string (?foo=bar) and decode URI +if (false !== $pos = strpos($uri, '?')) { + $uri = substr($uri, 0, $pos); +} +$uri = rawurldecode($uri); + +$routeInfo = $dispatcher->dispatch($httpMethod, $uri); +switch ($routeInfo[0]) { + case FastRoute\Dispatcher::NOT_FOUND: + // ... 404 Not Found + break; + case FastRoute\Dispatcher::METHOD_NOT_ALLOWED: + $allowedMethods = $routeInfo[1]; + // ... 405 Method Not Allowed + break; + case FastRoute\Dispatcher::FOUND: + $handler = $routeInfo[1]; + $vars = $routeInfo[2]; + // ... call $handler with $vars + break; +} +``` + +### Defining routes + +The routes are defined by calling the `FastRoute\simpleDispatcher()` function, which accepts +a callable taking a `FastRoute\RouteCollector` instance. The routes are added by calling +`addRoute()` on the collector instance: + +```php +$r->addRoute($method, $routePattern, $handler); +``` + +The `$method` is an uppercase HTTP method string for which a certain route should match. It +is possible to specify multiple valid methods using an array: + +```php +// These two calls +$r->addRoute('GET', '/test', 'handler'); +$r->addRoute('POST', '/test', 'handler'); +// Are equivalent to this one call +$r->addRoute(['GET', 'POST'], '/test', 'handler'); +``` + +By default the `$routePattern` uses a syntax where `{foo}` specifies a placeholder with name `foo` +and matching the regex `[^/]+`. To adjust the pattern the placeholder matches, you can specify +a custom pattern by writing `{bar:[0-9]+}`. Some examples: + +```php +// Matches /user/42, but not /user/xyz +$r->addRoute('GET', '/user/{id:\d+}', 'handler'); + +// Matches /user/foobar, but not /user/foo/bar +$r->addRoute('GET', '/user/{name}', 'handler'); + +// Matches /user/foo/bar as well +$r->addRoute('GET', '/user/{name:.+}', 'handler'); +``` + +Custom patterns for route placeholders cannot use capturing groups. For example `{lang:(en|de)}` +is not a valid placeholder, because `()` is a capturing group. Instead you can use either +`{lang:en|de}` or `{lang:(?:en|de)}`. + +Furthermore parts of the route enclosed in `[...]` are considered optional, so that `/foo[bar]` +will match both `/foo` and `/foobar`. Optional parts are only supported in a trailing position, +not in the middle of a route. + +```php +// This route +$r->addRoute('GET', '/user/{id:\d+}[/{name}]', 'handler'); +// Is equivalent to these two routes +$r->addRoute('GET', '/user/{id:\d+}', 'handler'); +$r->addRoute('GET', '/user/{id:\d+}/{name}', 'handler'); + +// Multiple nested optional parts are possible as well +$r->addRoute('GET', '/user[/{id:\d+}[/{name}]]', 'handler'); + +// This route is NOT valid, because optional parts can only occur at the end +$r->addRoute('GET', '/user[/{id:\d+}]/{name}', 'handler'); +``` + +The `$handler` parameter does not necessarily have to be a callback, it could also be a controller +class name or any other kind of data you wish to associate with the route. FastRoute only tells you +which handler corresponds to your URI, how you interpret it is up to you. + +### Caching + +The reason `simpleDispatcher` accepts a callback for defining the routes is to allow seamless +caching. By using `cachedDispatcher` instead of `simpleDispatcher` you can cache the generated +routing data and construct the dispatcher from the cached information: + +```php +addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0'); + $r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1'); + $r->addRoute('GET', '/user/{name}', 'handler2'); +}, [ + 'cacheFile' => __DIR__ . '/route.cache', /* required */ + 'cacheDisabled' => IS_DEBUG_ENABLED, /* optional, enabled by default */ +]); +``` + +The second parameter to the function is an options array, which can be used to specify the cache +file location, among other things. + +### Dispatching a URI + +A URI is dispatched by calling the `dispatch()` method of the created dispatcher. This method +accepts the HTTP method and a URI. Getting those two bits of information (and normalizing them +appropriately) is your job - this library is not bound to the PHP web SAPIs. + +The `dispatch()` method returns an array whose first element contains a status code. It is one +of `Dispatcher::NOT_FOUND`, `Dispatcher::METHOD_NOT_ALLOWED` and `Dispatcher::FOUND`. For the +method not allowed status the second array element contains a list of HTTP methods allowed for +the supplied URI. For example: + + [FastRoute\Dispatcher::METHOD_NOT_ALLOWED, ['GET', 'POST']] + +> **NOTE:** The HTTP specification requires that a `405 Method Not Allowed` response include the +`Allow:` header to detail available methods for the requested resource. Applications using FastRoute +should use the second array element to add this header when relaying a 405 response. + +For the found status the second array element is the handler that was associated with the route +and the third array element is a dictionary of placeholder names to their values. For example: + + /* Routing against GET /user/nikic/42 */ + + [FastRoute\Dispatcher::FOUND, 'handler0', ['name' => 'nikic', 'id' => '42']] + +### Overriding the route parser and dispatcher + +The routing process makes use of three components: A route parser, a data generator and a +dispatcher. The three components adhere to the following interfaces: + +```php + 'FastRoute\\RouteParser\\Std', + 'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased', + 'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased', +]); +``` + +The above options array corresponds to the defaults. By replacing `GroupCountBased` by +`GroupPosBased` you could switch to a different dispatching strategy. + +### A Note on HEAD Requests + +The HTTP spec requires servers to [support both GET and HEAD methods][2616-511]: + +> The methods GET and HEAD MUST be supported by all general-purpose servers + +To avoid forcing users to manually register HEAD routes for each resource we fallback to matching an +available GET route for a given resource. The PHP web SAPI transparently removes the entity body +from HEAD responses so this behavior has no effect on the vast majority of users. + +However, implementers using FastRoute outside the web SAPI environment (e.g. a custom server) MUST +NOT send entity bodies generated in response to HEAD requests. If you are a non-SAPI user this is +*your responsibility*; FastRoute has no purview to prevent you from breaking HTTP in such cases. + +Finally, note that applications MAY always specify their own HEAD method route for a given +resource to bypass this behavior entirely. + +### Credits + +This library is based on a router that [Levi Morrison][levi] implemented for the Aerys server. + +A large number of tests, as well as HTTP compliance considerations, were provided by [Daniel Lowrey][rdlowrey]. + + +[2616-511]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.1 "RFC 2616 Section 5.1.1" +[blog_post]: http://nikic.github.io/2014/02/18/Fast-request-routing-using-regular-expressions.html +[levi]: https://github.com/morrisonlevi +[rdlowrey]: https://github.com/rdlowrey diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/composer.json b/samples/server/petstore/slim/vendor/nikic/fast-route/composer.json new file mode 100644 index 000000000000..62aad22b0ce0 --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/composer.json @@ -0,0 +1,21 @@ +{ + "name": "nikic/fast-route", + "description": "Fast request router for PHP", + "keywords": ["routing", "router"], + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "require": { + "php": ">=5.4.0" + }, + "autoload": { + "psr-4": { + "FastRoute\\": "src/" + }, + "files": ["src/functions.php"] + } +} diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/phpunit.xml b/samples/server/petstore/slim/vendor/nikic/fast-route/phpunit.xml new file mode 100644 index 000000000000..3c807b6acbcd --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/phpunit.xml @@ -0,0 +1,24 @@ + + + + + + ./test/ + + + + + + ./src/ + + + diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/src/BadRouteException.php b/samples/server/petstore/slim/vendor/nikic/fast-route/src/BadRouteException.php new file mode 100644 index 000000000000..7e38479661e0 --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/src/BadRouteException.php @@ -0,0 +1,6 @@ + $route) { + $suffixLen++; + $suffix .= "\t"; + + $regexes[] = '(?:' . $regex . '/(\t{' . $suffixLen . '})\t{' . ($count - $suffixLen) . '})'; + $routeMap[$suffix] = [$route->handler, $route->variables]; + } + + $regex = '~^(?|' . implode('|', $regexes) . ')$~'; + return ['regex' => $regex, 'suffix' => '/' . $suffix, 'routeMap' => $routeMap]; + } +} diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php b/samples/server/petstore/slim/vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php new file mode 100644 index 000000000000..d51807f0772c --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/src/DataGenerator/GroupCountBased.php @@ -0,0 +1,28 @@ + $route) { + $numVariables = count($route->variables); + $numGroups = max($numGroups, $numVariables); + + $regexes[] = $regex . str_repeat('()', $numGroups - $numVariables); + $routeMap[$numGroups + 1] = [$route->handler, $route->variables]; + + ++$numGroups; + } + + $regex = '~^(?|' . implode('|', $regexes) . ')$~'; + return ['regex' => $regex, 'routeMap' => $routeMap]; + } +} + diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php b/samples/server/petstore/slim/vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php new file mode 100644 index 000000000000..4152f7a7efc9 --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/src/DataGenerator/GroupPosBased.php @@ -0,0 +1,25 @@ + $route) { + $regexes[] = $regex; + $routeMap[$offset] = [$route->handler, $route->variables]; + + $offset += count($route->variables); + } + + $regex = '~^(?:' . implode('|', $regexes) . ')$~'; + return ['regex' => $regex, 'routeMap' => $routeMap]; + } +} + diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/src/DataGenerator/MarkBased.php b/samples/server/petstore/slim/vendor/nikic/fast-route/src/DataGenerator/MarkBased.php new file mode 100644 index 000000000000..61359f5e73f6 --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/src/DataGenerator/MarkBased.php @@ -0,0 +1,25 @@ + $route) { + $regexes[] = $regex . '(*MARK:' . $markName . ')'; + $routeMap[$markName] = [$route->handler, $route->variables]; + + ++$markName; + } + + $regex = '~^(?|' . implode('|', $regexes) . ')$~'; + return ['regex' => $regex, 'routeMap' => $routeMap]; + } +} + diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php b/samples/server/petstore/slim/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php new file mode 100644 index 000000000000..713d8972f5ae --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php @@ -0,0 +1,144 @@ +isStaticRoute($routeData)) { + $this->addStaticRoute($httpMethod, $routeData, $handler); + } else { + $this->addVariableRoute($httpMethod, $routeData, $handler); + } + } + + public function getData() { + if (empty($this->methodToRegexToRoutesMap)) { + return [$this->staticRoutes, []]; + } + + return [$this->staticRoutes, $this->generateVariableRouteData()]; + } + + private function generateVariableRouteData() { + $data = []; + foreach ($this->methodToRegexToRoutesMap as $method => $regexToRoutesMap) { + $chunkSize = $this->computeChunkSize(count($regexToRoutesMap)); + $chunks = array_chunk($regexToRoutesMap, $chunkSize, true); + $data[$method] = array_map([$this, 'processChunk'], $chunks); + } + return $data; + } + + private function computeChunkSize($count) { + $numParts = max(1, round($count / $this->getApproxChunkSize())); + return ceil($count / $numParts); + } + + private function isStaticRoute($routeData) { + return count($routeData) === 1 && is_string($routeData[0]); + } + + private function addStaticRoute($httpMethod, $routeData, $handler) { + $routeStr = $routeData[0]; + + if (isset($this->staticRoutes[$httpMethod][$routeStr])) { + throw new BadRouteException(sprintf( + 'Cannot register two routes matching "%s" for method "%s"', + $routeStr, $httpMethod + )); + } + + if (isset($this->methodToRegexToRoutesMap[$httpMethod])) { + foreach ($this->methodToRegexToRoutesMap[$httpMethod] as $route) { + if ($route->matches($routeStr)) { + throw new BadRouteException(sprintf( + 'Static route "%s" is shadowed by previously defined variable route "%s" for method "%s"', + $routeStr, $route->regex, $httpMethod + )); + } + } + } + + $this->staticRoutes[$httpMethod][$routeStr] = $handler; + } + + private function addVariableRoute($httpMethod, $routeData, $handler) { + list($regex, $variables) = $this->buildRegexForRoute($routeData); + + if (isset($this->methodToRegexToRoutesMap[$httpMethod][$regex])) { + throw new BadRouteException(sprintf( + 'Cannot register two routes matching "%s" for method "%s"', + $regex, $httpMethod + )); + } + + $this->methodToRegexToRoutesMap[$httpMethod][$regex] = new Route( + $httpMethod, $handler, $regex, $variables + ); + } + + private function buildRegexForRoute($routeData) { + $regex = ''; + $variables = []; + foreach ($routeData as $part) { + if (is_string($part)) { + $regex .= preg_quote($part, '~'); + continue; + } + + list($varName, $regexPart) = $part; + + if (isset($variables[$varName])) { + throw new BadRouteException(sprintf( + 'Cannot use the same placeholder "%s" twice', $varName + )); + } + + if ($this->regexHasCapturingGroups($regexPart)) { + throw new BadRouteException(sprintf( + 'Regex "%s" for parameter "%s" contains a capturing group', + $regexPart, $varName + )); + } + + $variables[$varName] = $varName; + $regex .= '(' . $regexPart . ')'; + } + + return [$regex, $variables]; + } + + private function regexHasCapturingGroups($regex) { + if (false === strpos($regex, '(')) { + // Needs to have at least a ( to contain a capturing group + return false; + } + + // Semi-accurate detection for capturing groups + return preg_match( + '~ + (?: + \(\?\( + | \[ [^\]\\\\]* (?: \\\\ . [^\]\\\\]* )* \] + | \\\\ . + ) (*SKIP)(*FAIL) | + \( + (?! + \? (?! <(?![!=]) | P< | \' ) + | \* + ) + ~x', + $regex + ); + } +} diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher.php b/samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher.php new file mode 100644 index 000000000000..ea98009bd264 --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher.php @@ -0,0 +1,25 @@ + 'value', ...]] + * + * @param string $httpMethod + * @param string $uri + * + * @return array + */ + public function dispatch($httpMethod, $uri); +} diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php b/samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php new file mode 100644 index 000000000000..22ba2406f1e8 --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/CharCountBased.php @@ -0,0 +1,28 @@ +staticRouteMap, $this->variableRouteData) = $data; + } + + protected function dispatchVariableRoute($routeData, $uri) { + foreach ($routeData as $data) { + if (!preg_match($data['regex'], $uri . $data['suffix'], $matches)) { + continue; + } + + list($handler, $varNames) = $data['routeMap'][end($matches)]; + + $vars = []; + $i = 0; + foreach ($varNames as $varName) { + $vars[$varName] = $matches[++$i]; + } + return [self::FOUND, $handler, $vars]; + } + + return [self::NOT_FOUND]; + } +} diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php b/samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php new file mode 100644 index 000000000000..0abd32231309 --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/GroupCountBased.php @@ -0,0 +1,28 @@ +staticRouteMap, $this->variableRouteData) = $data; + } + + protected function dispatchVariableRoute($routeData, $uri) { + foreach ($routeData as $data) { + if (!preg_match($data['regex'], $uri, $matches)) { + continue; + } + + list($handler, $varNames) = $data['routeMap'][count($matches)]; + + $vars = []; + $i = 0; + foreach ($varNames as $varName) { + $vars[$varName] = $matches[++$i]; + } + return [self::FOUND, $handler, $vars]; + } + + return [self::NOT_FOUND]; + } +} diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php b/samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php new file mode 100644 index 000000000000..32227d4944d2 --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/GroupPosBased.php @@ -0,0 +1,30 @@ +staticRouteMap, $this->variableRouteData) = $data; + } + + protected function dispatchVariableRoute($routeData, $uri) { + foreach ($routeData as $data) { + if (!preg_match($data['regex'], $uri, $matches)) { + continue; + } + + // find first non-empty match + for ($i = 1; '' === $matches[$i]; ++$i); + + list($handler, $varNames) = $data['routeMap'][$i]; + + $vars = []; + foreach ($varNames as $varName) { + $vars[$varName] = $matches[$i++]; + } + return [self::FOUND, $handler, $vars]; + } + + return [self::NOT_FOUND]; + } +} diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/MarkBased.php b/samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/MarkBased.php new file mode 100644 index 000000000000..fefa71185711 --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/MarkBased.php @@ -0,0 +1,28 @@ +staticRouteMap, $this->variableRouteData) = $data; + } + + protected function dispatchVariableRoute($routeData, $uri) { + foreach ($routeData as $data) { + if (!preg_match($data['regex'], $uri, $matches)) { + continue; + } + + list($handler, $varNames) = $data['routeMap'][$matches['MARK']]; + + $vars = []; + $i = 0; + foreach ($varNames as $varName) { + $vars[$varName] = $matches[++$i]; + } + return [self::FOUND, $handler, $vars]; + } + + return [self::NOT_FOUND]; + } +} diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/RegexBasedAbstract.php b/samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/RegexBasedAbstract.php new file mode 100644 index 000000000000..8823b9b25280 --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/src/Dispatcher/RegexBasedAbstract.php @@ -0,0 +1,80 @@ +staticRouteMap[$httpMethod][$uri])) { + $handler = $this->staticRouteMap[$httpMethod][$uri]; + return [self::FOUND, $handler, []]; + } + + $varRouteData = $this->variableRouteData; + if (isset($varRouteData[$httpMethod])) { + $result = $this->dispatchVariableRoute($varRouteData[$httpMethod], $uri); + if ($result[0] === self::FOUND) { + return $result; + } + } + + // For HEAD requests, attempt fallback to GET + if ($httpMethod === 'HEAD') { + if (isset($this->staticRouteMap['GET'][$uri])) { + $handler = $this->staticRouteMap['GET'][$uri]; + return [self::FOUND, $handler, []]; + } + if (isset($varRouteData['GET'])) { + $result = $this->dispatchVariableRoute($varRouteData['GET'], $uri); + if ($result[0] === self::FOUND) { + return $result; + } + } + } + + // If nothing else matches, try fallback routes + if (isset($this->staticRouteMap['*'][$uri])) { + $handler = $this->staticRouteMap['*'][$uri]; + return [self::FOUND, $handler, []]; + } + if (isset($varRouteData['*'])) { + $result = $this->dispatchVariableRoute($varRouteData['*'], $uri); + if ($result[0] === self::FOUND) { + return $result; + } + } + + // Find allowed methods for this URI by matching against all other HTTP methods as well + $allowedMethods = []; + + foreach ($this->staticRouteMap as $method => $uriMap) { + if ($method !== $httpMethod && isset($uriMap[$uri])) { + $allowedMethods[] = $method; + } + } + + foreach ($varRouteData as $method => $routeData) { + if ($method === $httpMethod) { + continue; + } + + $result = $this->dispatchVariableRoute($routeData, $uri); + if ($result[0] === self::FOUND) { + $allowedMethods[] = $method; + } + } + + // If there are no allowed methods the route simply does not exist + if ($allowedMethods) { + return [self::METHOD_NOT_ALLOWED, $allowedMethods]; + } else { + return [self::NOT_FOUND]; + } + } +} diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/src/Route.php b/samples/server/petstore/slim/vendor/nikic/fast-route/src/Route.php new file mode 100644 index 000000000000..d71ded18ad24 --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/src/Route.php @@ -0,0 +1,38 @@ +httpMethod = $httpMethod; + $this->handler = $handler; + $this->regex = $regex; + $this->variables = $variables; + } + + /** + * Tests whether this route matches the given string. + * + * @param string $str + * + * @return bool + */ + public function matches($str) { + $regex = '~^' . $this->regex . '$~'; + return (bool) preg_match($regex, $str); + } +} + diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/src/RouteCollector.php b/samples/server/petstore/slim/vendor/nikic/fast-route/src/RouteCollector.php new file mode 100644 index 000000000000..4386bbf3aacc --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/src/RouteCollector.php @@ -0,0 +1,46 @@ +routeParser = $routeParser; + $this->dataGenerator = $dataGenerator; + } + + /** + * Adds a route to the collection. + * + * The syntax used in the $route string depends on the used route parser. + * + * @param string|string[] $httpMethod + * @param string $route + * @param mixed $handler + */ + public function addRoute($httpMethod, $route, $handler) { + $routeDatas = $this->routeParser->parse($route); + foreach ((array) $httpMethod as $method) { + foreach ($routeDatas as $routeData) { + $this->dataGenerator->addRoute($method, $routeData, $handler); + } + } + } + + /** + * Returns the collected route data, as provided by the data generator. + * + * @return array + */ + public function getData() { + return $this->dataGenerator->getData(); + } +} diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/src/RouteParser.php b/samples/server/petstore/slim/vendor/nikic/fast-route/src/RouteParser.php new file mode 100644 index 000000000000..c089c3151632 --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/src/RouteParser.php @@ -0,0 +1,36 @@ + $segment) { + if ($segment === '' && $n !== 0) { + throw new BadRouteException("Empty optional part"); + } + + $currentRoute .= $segment; + $routeDatas[] = $this->parsePlaceholders($currentRoute); + } + return $routeDatas; + } + + /** + * Parses a route string that does not contain optional segments. + */ + private function parsePlaceholders($route) { + if (!preg_match_all( + '~' . self::VARIABLE_REGEX . '~x', $route, $matches, + PREG_OFFSET_CAPTURE | PREG_SET_ORDER + )) { + return [$route]; + } + + $offset = 0; + $routeData = []; + foreach ($matches as $set) { + if ($set[0][1] > $offset) { + $routeData[] = substr($route, $offset, $set[0][1] - $offset); + } + $routeData[] = [ + $set[1][0], + isset($set[2]) ? trim($set[2][0]) : self::DEFAULT_DISPATCH_REGEX + ]; + $offset = $set[0][1] + strlen($set[0][0]); + } + + if ($offset != strlen($route)) { + $routeData[] = substr($route, $offset); + } + + return $routeData; + } +} diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/src/bootstrap.php b/samples/server/petstore/slim/vendor/nikic/fast-route/src/bootstrap.php new file mode 100644 index 000000000000..add216c7d01f --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/src/bootstrap.php @@ -0,0 +1,12 @@ + 'FastRoute\\RouteParser\\Std', + 'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased', + 'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased', + 'routeCollector' => 'FastRoute\\RouteCollector', + ]; + + /** @var RouteCollector $routeCollector */ + $routeCollector = new $options['routeCollector']( + new $options['routeParser'], new $options['dataGenerator'] + ); + $routeDefinitionCallback($routeCollector); + + return new $options['dispatcher']($routeCollector->getData()); + } + + /** + * @param callable $routeDefinitionCallback + * @param array $options + * + * @return Dispatcher + */ + function cachedDispatcher(callable $routeDefinitionCallback, array $options = []) { + $options += [ + 'routeParser' => 'FastRoute\\RouteParser\\Std', + 'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased', + 'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased', + 'routeCollector' => 'FastRoute\\RouteCollector', + 'cacheDisabled' => false, + ]; + + if (!isset($options['cacheFile'])) { + throw new \LogicException('Must specify "cacheFile" option'); + } + + if (!$options['cacheDisabled'] && file_exists($options['cacheFile'])) { + $dispatchData = require $options['cacheFile']; + if (!is_array($dispatchData)) { + throw new \RuntimeException('Invalid cache file "' . $options['cacheFile'] . '"'); + } + return new $options['dispatcher']($dispatchData); + } + + $routeCollector = new $options['routeCollector']( + new $options['routeParser'], new $options['dataGenerator'] + ); + $routeDefinitionCallback($routeCollector); + + /** @var RouteCollector $routeCollector */ + $dispatchData = $routeCollector->getData(); + file_put_contents( + $options['cacheFile'], + ' $this->getDataGeneratorClass(), + 'dispatcher' => $this->getDispatcherClass() + ]; + } + + /** + * @dataProvider provideFoundDispatchCases + */ + public function testFoundDispatches($method, $uri, $callback, $handler, $argDict) { + $dispatcher = \FastRoute\simpleDispatcher($callback, $this->generateDispatcherOptions()); + $info = $dispatcher->dispatch($method, $uri); + $this->assertSame($dispatcher::FOUND, $info[0]); + $this->assertSame($handler, $info[1]); + $this->assertSame($argDict, $info[2]); + } + + /** + * @dataProvider provideNotFoundDispatchCases + */ + public function testNotFoundDispatches($method, $uri, $callback) { + $dispatcher = \FastRoute\simpleDispatcher($callback, $this->generateDispatcherOptions()); + $routeInfo = $dispatcher->dispatch($method, $uri); + $this->assertFalse(isset($routeInfo[1]), + "NOT_FOUND result must only contain a single element in the returned info array" + ); + $this->assertSame($dispatcher::NOT_FOUND, $routeInfo[0]); + } + + /** + * @dataProvider provideMethodNotAllowedDispatchCases + */ + public function testMethodNotAllowedDispatches($method, $uri, $callback, $availableMethods) { + $dispatcher = \FastRoute\simpleDispatcher($callback, $this->generateDispatcherOptions()); + $routeInfo = $dispatcher->dispatch($method, $uri); + $this->assertTrue(isset($routeInfo[1]), + "METHOD_NOT_ALLOWED result must return an array of allowed methods at index 1" + ); + + list($routedStatus, $methodArray) = $dispatcher->dispatch($method, $uri); + $this->assertSame($dispatcher::METHOD_NOT_ALLOWED, $routedStatus); + $this->assertSame($availableMethods, $methodArray); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Cannot use the same placeholder "test" twice + */ + public function testDuplicateVariableNameError() { + \FastRoute\simpleDispatcher(function(RouteCollector $r) { + $r->addRoute('GET', '/foo/{test}/{test:\d+}', 'handler0'); + }, $this->generateDispatcherOptions()); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Cannot register two routes matching "/user/([^/]+)" for method "GET" + */ + public function testDuplicateVariableRoute() { + \FastRoute\simpleDispatcher(function(RouteCollector $r) { + $r->addRoute('GET', '/user/{id}', 'handler0'); // oops, forgot \d+ restriction ;) + $r->addRoute('GET', '/user/{name}', 'handler1'); + }, $this->generateDispatcherOptions()); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Cannot register two routes matching "/user" for method "GET" + */ + public function testDuplicateStaticRoute() { + \FastRoute\simpleDispatcher(function(RouteCollector $r) { + $r->addRoute('GET', '/user', 'handler0'); + $r->addRoute('GET', '/user', 'handler1'); + }, $this->generateDispatcherOptions()); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Static route "/user/nikic" is shadowed by previously defined variable route "/user/([^/]+)" for method "GET" + */ + public function testShadowedStaticRoute() { + \FastRoute\simpleDispatcher(function(RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('GET', '/user/nikic', 'handler1'); + }, $this->generateDispatcherOptions()); + } + + /** + * @expectedException \FastRoute\BadRouteException + * @expectedExceptionMessage Regex "(en|de)" for parameter "lang" contains a capturing group + */ + public function testCapturing() { + \FastRoute\simpleDispatcher(function(RouteCollector $r) { + $r->addRoute('GET', '/{lang:(en|de)}', 'handler0'); + }, $this->generateDispatcherOptions()); + } + + public function provideFoundDispatchCases() { + $cases = []; + + // 0 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/resource/123/456', 'handler0'); + }; + + $method = 'GET'; + $uri = '/resource/123/456'; + $handler = 'handler0'; + $argDict = []; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 1 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/handler0', 'handler0'); + $r->addRoute('GET', '/handler1', 'handler1'); + $r->addRoute('GET', '/handler2', 'handler2'); + }; + + $method = 'GET'; + $uri = '/handler2'; + $handler = 'handler2'; + $argDict = []; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 2 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0'); + $r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1'); + $r->addRoute('GET', '/user/{name}', 'handler2'); + }; + + $method = 'GET'; + $uri = '/user/rdlowrey'; + $handler = 'handler2'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 3 --------------------------------------------------------------------------------------> + + // reuse $callback from #2 + + $method = 'GET'; + $uri = '/user/12345'; + $handler = 'handler1'; + $argDict = ['id' => '12345']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 4 --------------------------------------------------------------------------------------> + + // reuse $callback from #3 + + $method = 'GET'; + $uri = '/user/NaN'; + $handler = 'handler2'; + $argDict = ['name' => 'NaN']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 5 --------------------------------------------------------------------------------------> + + // reuse $callback from #4 + + $method = 'GET'; + $uri = '/user/rdlowrey/12345'; + $handler = 'handler0'; + $argDict = ['name' => 'rdlowrey', 'id' => '12345']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 6 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/user/{id:[0-9]+}', 'handler0'); + $r->addRoute('GET', '/user/12345/extension', 'handler1'); + $r->addRoute('GET', '/user/{id:[0-9]+}.{extension}', 'handler2'); + + }; + + $method = 'GET'; + $uri = '/user/12345.svg'; + $handler = 'handler2'; + $argDict = ['id' => '12345', 'extension' => 'svg']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 7 ----- Test GET method fallback on HEAD route miss ------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler1'); + $r->addRoute('GET', '/static0', 'handler2'); + $r->addRoute('GET', '/static1', 'handler3'); + $r->addRoute('HEAD', '/static1', 'handler4'); + }; + + $method = 'HEAD'; + $uri = '/user/rdlowrey'; + $handler = 'handler0'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 8 ----- Test GET method fallback on HEAD route miss ------------------------------------> + + // reuse $callback from #7 + + $method = 'HEAD'; + $uri = '/user/rdlowrey/1234'; + $handler = 'handler1'; + $argDict = ['name' => 'rdlowrey', 'id' => '1234']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 9 ----- Test GET method fallback on HEAD route miss ------------------------------------> + + // reuse $callback from #8 + + $method = 'HEAD'; + $uri = '/static0'; + $handler = 'handler2'; + $argDict = []; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 10 ---- Test existing HEAD route used if available (no fallback) -----------------------> + + // reuse $callback from #9 + + $method = 'HEAD'; + $uri = '/static1'; + $handler = 'handler4'; + $argDict = []; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 11 ---- More specified routes are not shadowed by less specific of another method ------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('POST', '/user/{name:[a-z]+}', 'handler1'); + }; + + $method = 'POST'; + $uri = '/user/rdlowrey'; + $handler = 'handler1'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 12 ---- Handler of more specific routes is used, if it occurs first --------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('POST', '/user/{name:[a-z]+}', 'handler1'); + $r->addRoute('POST', '/user/{name}', 'handler2'); + }; + + $method = 'POST'; + $uri = '/user/rdlowrey'; + $handler = 'handler1'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 13 ---- Route with constant suffix -----------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/user/{name}', 'handler0'); + $r->addRoute('GET', '/user/{name}/edit', 'handler1'); + }; + + $method = 'GET'; + $uri = '/user/rdlowrey/edit'; + $handler = 'handler1'; + $argDict = ['name' => 'rdlowrey']; + + $cases[] = [$method, $uri, $callback, $handler, $argDict]; + + // 14 ---- Handle multiple methods with the same handler ----------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute(['GET', 'POST'], '/user', 'handlerGetPost'); + $r->addRoute(['DELETE'], '/user', 'handlerDelete'); + $r->addRoute([], '/user', 'handlerNone'); + }; + + $argDict = []; + $cases[] = ['GET', '/user', $callback, 'handlerGetPost', $argDict]; + $cases[] = ['POST', '/user', $callback, 'handlerGetPost', $argDict]; + $cases[] = ['DELETE', '/user', $callback, 'handlerDelete', $argDict]; + + // 15 ---- + + $callback = function(RouteCollector $r) { + $r->addRoute('POST', '/user.json', 'handler0'); + $r->addRoute('GET', '/{entity}.json', 'handler1'); + }; + + $cases[] = ['GET', '/user.json', $callback, 'handler1', ['entity' => 'user']]; + + // 16 ---- + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '', 'handler0'); + }; + + $cases[] = ['GET', '', $callback, 'handler0', []]; + + // 17 ---- + + $callback = function(RouteCollector $r) { + $r->addRoute('HEAD', '/a/{foo}', 'handler0'); + $r->addRoute('GET', '/b/{foo}', 'handler1'); + }; + + $cases[] = ['HEAD', '/b/bar', $callback, 'handler1', ['foo' => 'bar']]; + + // 18 ---- + + $callback = function(RouteCollector $r) { + $r->addRoute('HEAD', '/a', 'handler0'); + $r->addRoute('GET', '/b', 'handler1'); + }; + + $cases[] = ['HEAD', '/b', $callback, 'handler1', []]; + + // 19 ---- + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/foo', 'handler0'); + $r->addRoute('HEAD', '/{bar}', 'handler1'); + }; + + $cases[] = ['HEAD', '/foo', $callback, 'handler1', ['bar' => 'foo']]; + + // 20 ---- + + $callback = function(RouteCollector $r) { + $r->addRoute('*', '/user', 'handler0'); + $r->addRoute('*', '/{user}', 'handler1'); + $r->addRoute('GET', '/user', 'handler2'); + }; + + $cases[] = ['GET', '/user', $callback, 'handler2', []]; + + // 21 ---- + + $callback = function(RouteCollector $r) { + $r->addRoute('*', '/user', 'handler0'); + $r->addRoute('GET', '/user', 'handler1'); + }; + + $cases[] = ['POST', '/user', $callback, 'handler0', []]; + + // 22 ---- + + $cases[] = ['HEAD', '/user', $callback, 'handler1', []]; + + // 23 ---- + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/{bar}', 'handler0'); + $r->addRoute('*', '/foo', 'handler1'); + }; + + $cases[] = ['GET', '/foo', $callback, 'handler0', ['bar' => 'foo']]; + + // x --------------------------------------------------------------------------------------> + + return $cases; + } + + public function provideNotFoundDispatchCases() { + $cases = []; + + // 0 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/resource/123/456', 'handler0'); + }; + + $method = 'GET'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 1 --------------------------------------------------------------------------------------> + + // reuse callback from #0 + $method = 'POST'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 2 --------------------------------------------------------------------------------------> + + // reuse callback from #1 + $method = 'PUT'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 3 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/handler0', 'handler0'); + $r->addRoute('GET', '/handler1', 'handler1'); + $r->addRoute('GET', '/handler2', 'handler2'); + }; + + $method = 'GET'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 4 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0'); + $r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1'); + $r->addRoute('GET', '/user/{name}', 'handler2'); + }; + + $method = 'GET'; + $uri = '/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 5 --------------------------------------------------------------------------------------> + + // reuse callback from #4 + $method = 'GET'; + $uri = '/user/rdlowrey/12345/not-found'; + + $cases[] = [$method, $uri, $callback]; + + // 6 --------------------------------------------------------------------------------------> + + // reuse callback from #5 + $method = 'HEAD'; + + $cases[] = array($method, $uri, $callback); + + // x --------------------------------------------------------------------------------------> + + return $cases; + } + + public function provideMethodNotAllowedDispatchCases() { + $cases = []; + + // 0 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/resource/123/456', 'handler0'); + }; + + $method = 'POST'; + $uri = '/resource/123/456'; + $allowedMethods = ['GET']; + + $cases[] = [$method, $uri, $callback, $allowedMethods]; + + // 1 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/resource/123/456', 'handler0'); + $r->addRoute('POST', '/resource/123/456', 'handler1'); + $r->addRoute('PUT', '/resource/123/456', 'handler2'); + $r->addRoute('*', '/', 'handler3'); + }; + + $method = 'DELETE'; + $uri = '/resource/123/456'; + $allowedMethods = ['GET', 'POST', 'PUT']; + + $cases[] = [$method, $uri, $callback, $allowedMethods]; + + // 2 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0'); + $r->addRoute('POST', '/user/{name}/{id:[0-9]+}', 'handler1'); + $r->addRoute('PUT', '/user/{name}/{id:[0-9]+}', 'handler2'); + $r->addRoute('PATCH', '/user/{name}/{id:[0-9]+}', 'handler3'); + }; + + $method = 'DELETE'; + $uri = '/user/rdlowrey/42'; + $allowedMethods = ['GET', 'POST', 'PUT', 'PATCH']; + + $cases[] = [$method, $uri, $callback, $allowedMethods]; + + // 3 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute('POST', '/user/{name}', 'handler1'); + $r->addRoute('PUT', '/user/{name:[a-z]+}', 'handler2'); + $r->addRoute('PATCH', '/user/{name:[a-z]+}', 'handler3'); + }; + + $method = 'GET'; + $uri = '/user/rdlowrey'; + $allowedMethods = ['POST', 'PUT', 'PATCH']; + + $cases[] = [$method, $uri, $callback, $allowedMethods]; + + // 4 --------------------------------------------------------------------------------------> + + $callback = function(RouteCollector $r) { + $r->addRoute(['GET', 'POST'], '/user', 'handlerGetPost'); + $r->addRoute(['DELETE'], '/user', 'handlerDelete'); + $r->addRoute([], '/user', 'handlerNone'); + }; + + $cases[] = ['PUT', '/user', $callback, ['GET', 'POST', 'DELETE']]; + + // 5 + + $callback = function(RouteCollector $r) { + $r->addRoute('POST', '/user.json', 'handler0'); + $r->addRoute('GET', '/{entity}.json', 'handler1'); + }; + + $cases[] = ['PUT', '/user.json', $callback, ['POST', 'GET']]; + + // x --------------------------------------------------------------------------------------> + + return $cases; + } + +} diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/test/Dispatcher/GroupCountBasedTest.php b/samples/server/petstore/slim/vendor/nikic/fast-route/test/Dispatcher/GroupCountBasedTest.php new file mode 100644 index 000000000000..74820fcaf989 --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/test/Dispatcher/GroupCountBasedTest.php @@ -0,0 +1,13 @@ +markTestSkipped('PHP 5.6 required for MARK support'); + } + } + + protected function getDispatcherClass() { + return 'FastRoute\\Dispatcher\\MarkBased'; + } + + protected function getDataGeneratorClass() { + return 'FastRoute\\DataGenerator\\MarkBased'; + } +} diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/test/HackTypechecker/HackTypecheckerTest.php b/samples/server/petstore/slim/vendor/nikic/fast-route/test/HackTypechecker/HackTypecheckerTest.php new file mode 100644 index 000000000000..7bc6ebb310de --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/test/HackTypechecker/HackTypecheckerTest.php @@ -0,0 +1,39 @@ +markTestSkipped("HHVM only"); + } + if (!version_compare(HHVM_VERSION, '3.9.0', '>=')) { + $this->markTestSkipped('classname requires HHVM 3.9+'); + } + + // The typechecker recurses the whole tree, so it makes sure + // that everything in fixtures/ is valid when this runs. + + $output = array(); + $exit_code = null; + exec( + 'hh_server --check '.escapeshellarg(__DIR__.'/../../').' 2>&1', + $output, + $exit_code + ); + if ($exit_code === self::SERVER_ALREADY_RUNNING_CODE) { + $this->assertTrue( + $recurse, + "Typechecker still running after running hh_client stop" + ); + // Server already running - 3.10 => 3.11 regression: + // https://github.com/facebook/hhvm/issues/6646 + exec('hh_client stop 2>/dev/null'); + $this->testTypechecks(/* recurse = */ false); + return; + + } + $this->assertSame(0, $exit_code, implode("\n", $output)); + } +} diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/all_options.php b/samples/server/petstore/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/all_options.php new file mode 100644 index 000000000000..05a9af231b4a --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/all_options.php @@ -0,0 +1,29 @@ + {}, + shape( + 'routeParser' => \FastRoute\RouteParser\Std::class, + 'dataGenerator' => \FastRoute\DataGenerator\GroupCountBased::class, + 'dispatcher' => \FastRoute\Dispatcher\GroupCountBased::class, + 'routeCollector' => \FastRoute\RouteCollector::class, + ), + ); +} + +function all_options_cached(): \FastRoute\Dispatcher { + return \FastRoute\cachedDispatcher( + $collector ==> {}, + shape( + 'routeParser' => \FastRoute\RouteParser\Std::class, + 'dataGenerator' => \FastRoute\DataGenerator\GroupCountBased::class, + 'dispatcher' => \FastRoute\Dispatcher\GroupCountBased::class, + 'routeCollector' => \FastRoute\RouteCollector::class, + 'cacheFile' => '/dev/null', + 'cacheDisabled' => false, + ), + ); +} diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/empty_options.php b/samples/server/petstore/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/empty_options.php new file mode 100644 index 000000000000..61eb54190d9e --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/empty_options.php @@ -0,0 +1,11 @@ + {}, shape()); +} + +function empty_options_cached(): \FastRoute\Dispatcher { + return \FastRoute\cachedDispatcher($collector ==> {}, shape()); +} diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/no_options.php b/samples/server/petstore/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/no_options.php new file mode 100644 index 000000000000..44b5422f583e --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/test/HackTypechecker/fixtures/no_options.php @@ -0,0 +1,11 @@ + {}); +} + +function no_options_cached(): \FastRoute\Dispatcher { + return \FastRoute\cachedDispatcher($collector ==> {}); +} diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/test/RouteParser/StdTest.php b/samples/server/petstore/slim/vendor/nikic/fast-route/test/RouteParser/StdTest.php new file mode 100644 index 000000000000..41f194ba8b61 --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/test/RouteParser/StdTest.php @@ -0,0 +1,147 @@ +parse($routeString); + $this->assertSame($expectedRouteDatas, $routeDatas); + } + + /** @dataProvider provideTestParseError */ + public function testParseError($routeString, $expectedExceptionMessage) { + $parser = new Std(); + $this->setExpectedException('FastRoute\\BadRouteException', $expectedExceptionMessage); + $parser->parse($routeString); + } + + public function provideTestParse() { + return [ + [ + '/test', + [ + ['/test'], + ] + ], + [ + '/test/{param}', + [ + ['/test/', ['param', '[^/]+']], + ] + ], + [ + '/te{ param }st', + [ + ['/te', ['param', '[^/]+'], 'st'] + ] + ], + [ + '/test/{param1}/test2/{param2}', + [ + ['/test/', ['param1', '[^/]+'], '/test2/', ['param2', '[^/]+']] + ] + ], + [ + '/test/{param:\d+}', + [ + ['/test/', ['param', '\d+']] + ] + ], + [ + '/test/{ param : \d{1,9} }', + [ + ['/test/', ['param', '\d{1,9}']] + ] + ], + [ + '/test[opt]', + [ + ['/test'], + ['/testopt'], + ] + ], + [ + '/test[/{param}]', + [ + ['/test'], + ['/test/', ['param', '[^/]+']], + ] + ], + [ + '/{param}[opt]', + [ + ['/', ['param', '[^/]+']], + ['/', ['param', '[^/]+'], 'opt'] + ] + ], + [ + '/test[/{name}[/{id:[0-9]+}]]', + [ + ['/test'], + ['/test/', ['name', '[^/]+']], + ['/test/', ['name', '[^/]+'], '/', ['id', '[0-9]+']], + ] + ], + [ + '', + [ + [''], + ] + ], + [ + '[test]', + [ + [''], + ['test'], + ] + ], + [ + '/{foo-bar}', + [ + ['/', ['foo-bar', '[^/]+']] + ] + ], + [ + '/{_foo:.*}', + [ + ['/', ['_foo', '.*']] + ] + ], + ]; + } + + public function provideTestParseError() { + return [ + [ + '/test[opt', + "Number of opening '[' and closing ']' does not match" + ], + [ + '/test[opt[opt2]', + "Number of opening '[' and closing ']' does not match" + ], + [ + '/testopt]', + "Number of opening '[' and closing ']' does not match" + ], + [ + '/test[]', + "Empty optional part" + ], + [ + '/test[[opt]]', + "Empty optional part" + ], + [ + '[[test]]', + "Empty optional part" + ], + [ + '/test[/opt]/required', + "Optional segments can only occur at the end of a route" + ], + ]; + } +} diff --git a/samples/server/petstore/slim/vendor/nikic/fast-route/test/bootstrap.php b/samples/server/petstore/slim/vendor/nikic/fast-route/test/bootstrap.php new file mode 100644 index 000000000000..27e6d4c8fbdc --- /dev/null +++ b/samples/server/petstore/slim/vendor/nikic/fast-route/test/bootstrap.php @@ -0,0 +1,11 @@ +> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`; fi + +script: + - cd ext/pimple + - if [ "$PIMPLE_EXT" == "yes" ]; then yes n | make test | tee output ; grep -E 'Tests failed +. +0' output; fi + - cd ../.. + - phpunit + +matrix: + exclude: + - php: hhvm + env: PIMPLE_EXT=yes diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/CHANGELOG b/samples/server/petstore/slim/vendor/pimple/pimple/CHANGELOG new file mode 100644 index 000000000000..cc679972ec76 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/CHANGELOG @@ -0,0 +1,35 @@ +* 3.0.2 (2015-09-11) + + * refactored the C extension + * minor non-significant changes + +* 3.0.1 (2015-07-30) + + * simplified some code + * fixed a segfault in the C extension + +* 3.0.0 (2014-07-24) + + * removed the Pimple class alias (use Pimple\Container instead) + +* 2.1.1 (2014-07-24) + + * fixed compiler warnings for the C extension + * fixed code when dealing with circular references + +* 2.1.0 (2014-06-24) + + * moved the Pimple to Pimple\Container (with a BC layer -- Pimple is now a + deprecated alias which will be removed in Pimple 3.0) + * added Pimple\ServiceProviderInterface (and Pimple::register()) + +* 2.0.0 (2014-02-10) + + * changed extend to automatically re-assign the extended service and keep it as shared or factory + (to keep BC, extend still returns the extended service) + * changed services to be shared by default (use factory() for factory + services) + +* 1.0.0 + + * initial version diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/LICENSE b/samples/server/petstore/slim/vendor/pimple/pimple/LICENSE new file mode 100644 index 000000000000..d7949e2fb35e --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2009-2015 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/README.rst b/samples/server/petstore/slim/vendor/pimple/pimple/README.rst new file mode 100644 index 000000000000..93fb35a89b76 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/README.rst @@ -0,0 +1,201 @@ +Pimple +====== + +.. caution:: + + This is the documentation for Pimple 3.x. If you are using Pimple 1.x, read + the `Pimple 1.x documentation`_. Reading the Pimple 1.x code is also a good + way to learn more about how to create a simple Dependency Injection + Container (recent versions of Pimple are more focused on performance). + +Pimple is a small Dependency Injection Container for PHP. + +Installation +------------ + +Before using Pimple in your project, add it to your ``composer.json`` file: + +.. code-block:: bash + + $ ./composer.phar require pimple/pimple ~3.0 + +Alternatively, Pimple is also available as a PHP C extension: + +.. code-block:: bash + + $ git clone https://github.com/silexphp/Pimple + $ cd Pimple/ext/pimple + $ phpize + $ ./configure + $ make + $ make install + +Usage +----- + +Creating a container is a matter of creating a ``Container`` instance: + +.. code-block:: php + + use Pimple\Container; + + $container = new Container(); + +As many other dependency injection containers, Pimple manages two different +kind of data: **services** and **parameters**. + +Defining Services +~~~~~~~~~~~~~~~~~ + +A service is an object that does something as part of a larger system. Examples +of services: a database connection, a templating engine, or a mailer. Almost +any **global** object can be a service. + +Services are defined by **anonymous functions** that return an instance of an +object: + +.. code-block:: php + + // define some services + $container['session_storage'] = function ($c) { + return new SessionStorage('SESSION_ID'); + }; + + $container['session'] = function ($c) { + return new Session($c['session_storage']); + }; + +Notice that the anonymous function has access to the current container +instance, allowing references to other services or parameters. + +As objects are only created when you get them, the order of the definitions +does not matter. + +Using the defined services is also very easy: + +.. code-block:: php + + // get the session object + $session = $container['session']; + + // the above call is roughly equivalent to the following code: + // $storage = new SessionStorage('SESSION_ID'); + // $session = new Session($storage); + +Defining Factory Services +~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, each time you get a service, Pimple returns the **same instance** +of it. If you want a different instance to be returned for all calls, wrap your +anonymous function with the ``factory()`` method + +.. code-block:: php + + $container['session'] = $container->factory(function ($c) { + return new Session($c['session_storage']); + }); + +Now, each call to ``$container['session']`` returns a new instance of the +session. + +Defining Parameters +~~~~~~~~~~~~~~~~~~~ + +Defining a parameter allows to ease the configuration of your container from +the outside and to store global values: + +.. code-block:: php + + // define some parameters + $container['cookie_name'] = 'SESSION_ID'; + $container['session_storage_class'] = 'SessionStorage'; + +If you change the ``session_storage`` service definition like below: + +.. code-block:: php + + $container['session_storage'] = function ($c) { + return new $c['session_storage_class']($c['cookie_name']); + }; + +You can now easily change the cookie name by overriding the +``session_storage_class`` parameter instead of redefining the service +definition. + +Protecting Parameters +~~~~~~~~~~~~~~~~~~~~~ + +Because Pimple sees anonymous functions as service definitions, you need to +wrap anonymous functions with the ``protect()`` method to store them as +parameters: + +.. code-block:: php + + $container['random_func'] = $container->protect(function () { + return rand(); + }); + +Modifying Services after Definition +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In some cases you may want to modify a service definition after it has been +defined. You can use the ``extend()`` method to define additional code to be +run on your service just after it is created: + +.. code-block:: php + + $container['session_storage'] = function ($c) { + return new $c['session_storage_class']($c['cookie_name']); + }; + + $container->extend('session_storage', function ($storage, $c) { + $storage->...(); + + return $storage; + }); + +The first argument is the name of the service to extend, the second a function +that gets access to the object instance and the container. + +Extending a Container +~~~~~~~~~~~~~~~~~~~~~ + +If you use the same libraries over and over, you might want to reuse some +services from one project to the next one; package your services into a +**provider** by implementing ``Pimple\ServiceProviderInterface``: + +.. code-block:: php + + use Pimple\Container; + + class FooProvider implements Pimple\ServiceProviderInterface + { + public function register(Container $pimple) + { + // register some services and parameters + // on $pimple + } + } + +Then, register the provider on a Container: + +.. code-block:: php + + $pimple->register(new FooProvider()); + +Fetching the Service Creation Function +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When you access an object, Pimple automatically calls the anonymous function +that you defined, which creates the service object for you. If you want to get +raw access to this function, you can use the ``raw()`` method: + +.. code-block:: php + + $container['session'] = function ($c) { + return new Session($c['session_storage']); + }; + + $sessionFunction = $container->raw('session'); + +.. _Pimple 1.x documentation: https://github.com/silexphp/Pimple/tree/1.1 diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/composer.json b/samples/server/petstore/slim/vendor/pimple/pimple/composer.json new file mode 100644 index 000000000000..a5268f161185 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/composer.json @@ -0,0 +1,25 @@ +{ + "name": "pimple/pimple", + "type": "library", + "description": "Pimple, a simple Dependency Injection Container", + "keywords": ["dependency injection", "container"], + "homepage": "http://pimple.sensiolabs.org", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "require": { + "php": ">=5.3.0" + }, + "autoload": { + "psr-0": { "Pimple": "src/" } + }, + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + } +} diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/.gitignore b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/.gitignore new file mode 100644 index 000000000000..1861088ac1f6 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/.gitignore @@ -0,0 +1,30 @@ +*.sw* +.deps +Makefile +Makefile.fragments +Makefile.global +Makefile.objects +acinclude.m4 +aclocal.m4 +build/ +config.cache +config.guess +config.h +config.h.in +config.log +config.nice +config.status +config.sub +configure +configure.in +install-sh +libtool +ltmain.sh +missing +mkinstalldirs +run-tests.php +*.loT +.libs/ +modules/ +*.la +*.lo diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/README.md b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/README.md new file mode 100644 index 000000000000..7b39eb2929ea --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/README.md @@ -0,0 +1,12 @@ +This is Pimple 2 implemented in C + +* PHP >= 5.3 +* Not tested under Windows, might work + +Install +======= + + > phpize + > ./configure + > make + > make install diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/config.m4 b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/config.m4 new file mode 100644 index 000000000000..c9ba17ddbd58 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/config.m4 @@ -0,0 +1,63 @@ +dnl $Id$ +dnl config.m4 for extension pimple + +dnl Comments in this file start with the string 'dnl'. +dnl Remove where necessary. This file will not work +dnl without editing. + +dnl If your extension references something external, use with: + +dnl PHP_ARG_WITH(pimple, for pimple support, +dnl Make sure that the comment is aligned: +dnl [ --with-pimple Include pimple support]) + +dnl Otherwise use enable: + +PHP_ARG_ENABLE(pimple, whether to enable pimple support, +dnl Make sure that the comment is aligned: +[ --enable-pimple Enable pimple support]) + +if test "$PHP_PIMPLE" != "no"; then + dnl Write more examples of tests here... + + dnl # --with-pimple -> check with-path + dnl SEARCH_PATH="/usr/local /usr" # you might want to change this + dnl SEARCH_FOR="/include/pimple.h" # you most likely want to change this + dnl if test -r $PHP_PIMPLE/$SEARCH_FOR; then # path given as parameter + dnl PIMPLE_DIR=$PHP_PIMPLE + dnl else # search default path list + dnl AC_MSG_CHECKING([for pimple files in default path]) + dnl for i in $SEARCH_PATH ; do + dnl if test -r $i/$SEARCH_FOR; then + dnl PIMPLE_DIR=$i + dnl AC_MSG_RESULT(found in $i) + dnl fi + dnl done + dnl fi + dnl + dnl if test -z "$PIMPLE_DIR"; then + dnl AC_MSG_RESULT([not found]) + dnl AC_MSG_ERROR([Please reinstall the pimple distribution]) + dnl fi + + dnl # --with-pimple -> add include path + dnl PHP_ADD_INCLUDE($PIMPLE_DIR/include) + + dnl # --with-pimple -> check for lib and symbol presence + dnl LIBNAME=pimple # you may want to change this + dnl LIBSYMBOL=pimple # you most likely want to change this + + dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, + dnl [ + dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $PIMPLE_DIR/lib, PIMPLE_SHARED_LIBADD) + dnl AC_DEFINE(HAVE_PIMPLELIB,1,[ ]) + dnl ],[ + dnl AC_MSG_ERROR([wrong pimple lib version or lib not found]) + dnl ],[ + dnl -L$PIMPLE_DIR/lib -lm + dnl ]) + dnl + dnl PHP_SUBST(PIMPLE_SHARED_LIBADD) + + PHP_NEW_EXTENSION(pimple, pimple.c, $ext_shared) +fi diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/config.w32 b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/config.w32 new file mode 100644 index 000000000000..39857b3254be --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/config.w32 @@ -0,0 +1,13 @@ +// $Id$ +// vim:ft=javascript + +// If your extension references something external, use ARG_WITH +// ARG_WITH("pimple", "for pimple support", "no"); + +// Otherwise, use ARG_ENABLE +// ARG_ENABLE("pimple", "enable pimple support", "no"); + +if (PHP_PIMPLE != "no") { + EXTENSION("pimple", "pimple.c"); +} + diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/php_pimple.h b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/php_pimple.h new file mode 100644 index 000000000000..49431f08a846 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/php_pimple.h @@ -0,0 +1,121 @@ + +/* + * This file is part of Pimple. + * + * Copyright (c) 2014 Fabien Potencier + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef PHP_PIMPLE_H +#define PHP_PIMPLE_H + +extern zend_module_entry pimple_module_entry; +#define phpext_pimple_ptr &pimple_module_entry + +#ifdef PHP_WIN32 +# define PHP_PIMPLE_API __declspec(dllexport) +#elif defined(__GNUC__) && __GNUC__ >= 4 +# define PHP_PIMPLE_API __attribute__ ((visibility("default"))) +#else +# define PHP_PIMPLE_API +#endif + +#ifdef ZTS +#include "TSRM.h" +#endif + +#define PIMPLE_VERSION "3.0.2" +#define PIMPLE_NS "Pimple" + +#define PIMPLE_DEFAULT_ZVAL_CACHE_NUM 5 +#define PIMPLE_DEFAULT_ZVAL_VALUES_NUM 10 + +zend_module_entry *get_module(void); + +PHP_MINIT_FUNCTION(pimple); +PHP_MINFO_FUNCTION(pimple); + +PHP_METHOD(Pimple, __construct); +PHP_METHOD(Pimple, factory); +PHP_METHOD(Pimple, protect); +PHP_METHOD(Pimple, raw); +PHP_METHOD(Pimple, extend); +PHP_METHOD(Pimple, keys); +PHP_METHOD(Pimple, register); +PHP_METHOD(Pimple, offsetSet); +PHP_METHOD(Pimple, offsetUnset); +PHP_METHOD(Pimple, offsetGet); +PHP_METHOD(Pimple, offsetExists); + +PHP_METHOD(PimpleClosure, invoker); + +typedef struct _pimple_bucket_value { + zval *value; /* Must be the first element */ + zval *raw; + zend_object_handle handle_num; + enum { + PIMPLE_IS_PARAM = 0, + PIMPLE_IS_SERVICE = 2 + } type; + zend_bool initialized; + zend_fcall_info_cache fcc; +} pimple_bucket_value; + +typedef struct _pimple_object { + zend_object zobj; + HashTable values; + HashTable factories; + HashTable protected; +} pimple_object; + +typedef struct _pimple_closure_object { + zend_object zobj; + zval *callable; + zval *factory; +} pimple_closure_object; + +static const char sensiolabs_logo[] = ""; + +static int pimple_zval_to_pimpleval(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC); +static int pimple_zval_is_valid_callback(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC); + +static void pimple_bucket_dtor(pimple_bucket_value *bucket); +static void pimple_free_bucket(pimple_bucket_value *bucket); + +static zval *pimple_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC); +static void pimple_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC); +static int pimple_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC); +static void pimple_object_unset_dimension(zval *object, zval *offset TSRMLS_DC); +static zend_object_value pimple_object_create(zend_class_entry *ce TSRMLS_DC); +static void pimple_free_object_storage(pimple_object *obj TSRMLS_DC); + +static void pimple_closure_free_object_storage(pimple_closure_object *obj TSRMLS_DC); +static zend_object_value pimple_closure_object_create(zend_class_entry *ce TSRMLS_DC); +static zend_function *pimple_closure_get_constructor(zval * TSRMLS_DC); +static int pimple_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC); + +#ifdef ZTS +#define PIMPLE_G(v) TSRMG(pimple_globals_id, zend_pimple_globals *, v) +#else +#define PIMPLE_G(v) (pimple_globals.v) +#endif + +#endif /* PHP_PIMPLE_H */ + diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/pimple.c b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/pimple.c new file mode 100644 index 000000000000..239c01d683dd --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/pimple.c @@ -0,0 +1,922 @@ + +/* + * This file is part of Pimple. + * + * Copyright (c) 2014 Fabien Potencier + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_ini.h" +#include "ext/standard/info.h" +#include "php_pimple.h" +#include "pimple_compat.h" +#include "zend_interfaces.h" +#include "zend.h" +#include "Zend/zend_closures.h" +#include "ext/spl/spl_exceptions.h" +#include "Zend/zend_exceptions.h" +#include "main/php_output.h" +#include "SAPI.h" + +static zend_class_entry *pimple_ce; +static zend_object_handlers pimple_object_handlers; +static zend_class_entry *pimple_closure_ce; +static zend_class_entry *pimple_serviceprovider_ce; +static zend_object_handlers pimple_closure_object_handlers; +static zend_internal_function pimple_closure_invoker_function; + +#define FETCH_DIM_HANDLERS_VARS pimple_object *pimple_obj = NULL; \ + ulong index; \ + pimple_obj = (pimple_object *)zend_object_store_get_object(object TSRMLS_CC); \ + +#define PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS do { \ + if (ce != pimple_ce) { \ + zend_hash_find(&ce->function_table, ZEND_STRS("offsetget"), (void **)&function); \ + if (function->common.scope != ce) { /* if the function is not defined in this actual class */ \ + pimple_object_handlers.read_dimension = pimple_object_read_dimension; /* then overwrite the handler to use custom one */ \ + } \ + zend_hash_find(&ce->function_table, ZEND_STRS("offsetset"), (void **)&function); \ + if (function->common.scope != ce) { \ + pimple_object_handlers.write_dimension = pimple_object_write_dimension; \ + } \ + zend_hash_find(&ce->function_table, ZEND_STRS("offsetexists"), (void **)&function); \ + if (function->common.scope != ce) { \ + pimple_object_handlers.has_dimension = pimple_object_has_dimension; \ + } \ + zend_hash_find(&ce->function_table, ZEND_STRS("offsetunset"), (void **)&function); \ + if (function->common.scope != ce) { \ + pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \ + } \ + } else { \ + pimple_object_handlers.read_dimension = pimple_object_read_dimension; \ + pimple_object_handlers.write_dimension = pimple_object_write_dimension; \ + pimple_object_handlers.has_dimension = pimple_object_has_dimension; \ + pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \ + }\ + } while(0); + +#define PIMPLE_CALL_CB do { \ + zend_fcall_info_argn(&fci TSRMLS_CC, 1, &object); \ + fci.size = sizeof(fci); \ + fci.object_ptr = retval->fcc.object_ptr; \ + fci.function_name = retval->value; \ + fci.no_separation = 1; \ + fci.retval_ptr_ptr = &retval_ptr_ptr; \ +\ + zend_call_function(&fci, &retval->fcc TSRMLS_CC); \ + efree(fci.params); \ + if (EG(exception)) { \ + return EG(uninitialized_zval_ptr); \ + } \ + } while(0); + +ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 0) +ZEND_ARG_ARRAY_INFO(0, value, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetset, 0, 0, 2) +ZEND_ARG_INFO(0, offset) +ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetget, 0, 0, 1) +ZEND_ARG_INFO(0, offset) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetexists, 0, 0, 1) +ZEND_ARG_INFO(0, offset) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetunset, 0, 0, 1) +ZEND_ARG_INFO(0, offset) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_factory, 0, 0, 1) +ZEND_ARG_INFO(0, callable) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_protect, 0, 0, 1) +ZEND_ARG_INFO(0, callable) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_raw, 0, 0, 1) +ZEND_ARG_INFO(0, id) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_extend, 0, 0, 2) +ZEND_ARG_INFO(0, id) +ZEND_ARG_INFO(0, callable) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_keys, 0, 0, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_register, 0, 0, 1) +ZEND_ARG_OBJ_INFO(0, provider, Pimple\\ServiceProviderInterface, 0) +ZEND_ARG_ARRAY_INFO(0, values, 1) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_serviceprovider_register, 0, 0, 1) +ZEND_ARG_OBJ_INFO(0, pimple, Pimple\\Container, 0) +ZEND_END_ARG_INFO() + +static const zend_function_entry pimple_ce_functions[] = { + PHP_ME(Pimple, __construct, arginfo___construct, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, factory, arginfo_factory, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, protect, arginfo_protect, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, raw, arginfo_raw, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, extend, arginfo_extend, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, keys, arginfo_keys, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, register, arginfo_register, ZEND_ACC_PUBLIC) + + PHP_ME(Pimple, offsetSet, arginfo_offsetset, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, offsetGet, arginfo_offsetget, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, offsetExists, arginfo_offsetexists, ZEND_ACC_PUBLIC) + PHP_ME(Pimple, offsetUnset, arginfo_offsetunset, ZEND_ACC_PUBLIC) + PHP_FE_END +}; + +static const zend_function_entry pimple_serviceprovider_iface_ce_functions[] = { + PHP_ABSTRACT_ME(ServiceProviderInterface, register, arginfo_serviceprovider_register) + PHP_FE_END +}; + +static void pimple_closure_free_object_storage(pimple_closure_object *obj TSRMLS_DC) +{ + zend_object_std_dtor(&obj->zobj TSRMLS_CC); + if (obj->factory) { + zval_ptr_dtor(&obj->factory); + } + if (obj->callable) { + zval_ptr_dtor(&obj->callable); + } + efree(obj); +} + +static void pimple_free_object_storage(pimple_object *obj TSRMLS_DC) +{ + zend_hash_destroy(&obj->factories); + zend_hash_destroy(&obj->protected); + zend_hash_destroy(&obj->values); + zend_object_std_dtor(&obj->zobj TSRMLS_CC); + efree(obj); +} + +static void pimple_free_bucket(pimple_bucket_value *bucket) +{ + if (bucket->raw) { + zval_ptr_dtor(&bucket->raw); + } +} + +static zend_object_value pimple_closure_object_create(zend_class_entry *ce TSRMLS_DC) +{ + zend_object_value retval; + pimple_closure_object *pimple_closure_obj = NULL; + + pimple_closure_obj = ecalloc(1, sizeof(pimple_closure_object)); + ZEND_OBJ_INIT(&pimple_closure_obj->zobj, ce); + + pimple_closure_object_handlers.get_constructor = pimple_closure_get_constructor; + retval.handlers = &pimple_closure_object_handlers; + retval.handle = zend_objects_store_put(pimple_closure_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_closure_free_object_storage, NULL TSRMLS_CC); + + return retval; +} + +static zend_function *pimple_closure_get_constructor(zval *obj TSRMLS_DC) +{ + zend_error(E_ERROR, "Pimple\\ContainerClosure is an internal class and cannot be instantiated"); + + return NULL; +} + +static int pimple_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC) +{ + *zobj_ptr = obj; + *ce_ptr = Z_OBJCE_P(obj); + *fptr_ptr = (zend_function *)&pimple_closure_invoker_function; + + return SUCCESS; +} + +static zend_object_value pimple_object_create(zend_class_entry *ce TSRMLS_DC) +{ + zend_object_value retval; + pimple_object *pimple_obj = NULL; + zend_function *function = NULL; + + pimple_obj = emalloc(sizeof(pimple_object)); + ZEND_OBJ_INIT(&pimple_obj->zobj, ce); + + PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS + + retval.handlers = &pimple_object_handlers; + retval.handle = zend_objects_store_put(pimple_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_free_object_storage, NULL TSRMLS_CC); + + zend_hash_init(&pimple_obj->factories, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0); + zend_hash_init(&pimple_obj->protected, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0); + zend_hash_init(&pimple_obj->values, PIMPLE_DEFAULT_ZVAL_VALUES_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0); + + return retval; +} + +static void pimple_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC) +{ + FETCH_DIM_HANDLERS_VARS + + pimple_bucket_value pimple_value = {0}, *found_value = NULL; + ulong hash; + + pimple_zval_to_pimpleval(value, &pimple_value TSRMLS_CC); + + if (!offset) {/* $p[] = 'foo' when not overloaded */ + zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL); + Z_ADDREF_P(value); + return; + } + + switch (Z_TYPE_P(offset)) { + case IS_STRING: + hash = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + zend_hash_quick_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void **)&found_value); + if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) { + pimple_free_bucket(&pimple_value); + zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot override frozen service \"%s\".", Z_STRVAL_P(offset)); + return; + } + if (zend_hash_quick_update(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) { + pimple_free_bucket(&pimple_value); + return; + } + Z_ADDREF_P(value); + break; + case IS_DOUBLE: + case IS_BOOL: + case IS_LONG: + if (Z_TYPE_P(offset) == IS_DOUBLE) { + index = (ulong)Z_DVAL_P(offset); + } else { + index = Z_LVAL_P(offset); + } + zend_hash_index_find(&pimple_obj->values, index, (void **)&found_value); + if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) { + pimple_free_bucket(&pimple_value); + zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot override frozen service \"%ld\".", index); + return; + } + if (zend_hash_index_update(&pimple_obj->values, index, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) { + pimple_free_bucket(&pimple_value); + return; + } + Z_ADDREF_P(value); + break; + case IS_NULL: /* $p[] = 'foo' when overloaded */ + zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL); + Z_ADDREF_P(value); + break; + default: + pimple_free_bucket(&pimple_value); + zend_error(E_WARNING, "Unsupported offset type"); + } +} + +static void pimple_object_unset_dimension(zval *object, zval *offset TSRMLS_DC) +{ + FETCH_DIM_HANDLERS_VARS + + switch (Z_TYPE_P(offset)) { + case IS_STRING: + zend_symtable_del(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + zend_symtable_del(&pimple_obj->factories, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + zend_symtable_del(&pimple_obj->protected, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + break; + case IS_DOUBLE: + case IS_BOOL: + case IS_LONG: + if (Z_TYPE_P(offset) == IS_DOUBLE) { + index = (ulong)Z_DVAL_P(offset); + } else { + index = Z_LVAL_P(offset); + } + zend_hash_index_del(&pimple_obj->values, index); + zend_hash_index_del(&pimple_obj->factories, index); + zend_hash_index_del(&pimple_obj->protected, index); + break; + default: + zend_error(E_WARNING, "Unsupported offset type"); + } +} + +static int pimple_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC) +{ + FETCH_DIM_HANDLERS_VARS + + pimple_bucket_value *retval = NULL; + + switch (Z_TYPE_P(offset)) { + case IS_STRING: + if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == SUCCESS) { + switch (check_empty) { + case 0: /* isset */ + return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;) */ + case 1: /* empty */ + default: + return zend_is_true(retval->value); + } + } + return 0; + break; + case IS_DOUBLE: + case IS_BOOL: + case IS_LONG: + if (Z_TYPE_P(offset) == IS_DOUBLE) { + index = (ulong)Z_DVAL_P(offset); + } else { + index = Z_LVAL_P(offset); + } + if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == SUCCESS) { + switch (check_empty) { + case 0: /* isset */ + return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;)*/ + case 1: /* empty */ + default: + return zend_is_true(retval->value); + } + } + return 0; + break; + default: + zend_error(E_WARNING, "Unsupported offset type"); + return 0; + } +} + +static zval *pimple_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) +{ + FETCH_DIM_HANDLERS_VARS + + pimple_bucket_value *retval = NULL; + zend_fcall_info fci = {0}; + zval *retval_ptr_ptr = NULL; + + switch (Z_TYPE_P(offset)) { + case IS_STRING: + if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == FAILURE) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" is not defined.", Z_STRVAL_P(offset)); + return EG(uninitialized_zval_ptr); + } + break; + case IS_DOUBLE: + case IS_BOOL: + case IS_LONG: + if (Z_TYPE_P(offset) == IS_DOUBLE) { + index = (ulong)Z_DVAL_P(offset); + } else { + index = Z_LVAL_P(offset); + } + if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == FAILURE) { + return EG(uninitialized_zval_ptr); + } + break; + case IS_NULL: /* $p[][3] = 'foo' first dim access */ + return EG(uninitialized_zval_ptr); + break; + default: + zend_error(E_WARNING, "Unsupported offset type"); + return EG(uninitialized_zval_ptr); + } + + if(retval->type == PIMPLE_IS_PARAM) { + return retval->value; + } + + if (zend_hash_index_exists(&pimple_obj->protected, retval->handle_num)) { + /* Service is protected, return the value every time */ + return retval->value; + } + + if (zend_hash_index_exists(&pimple_obj->factories, retval->handle_num)) { + /* Service is a factory, call it everytime and never cache its result */ + PIMPLE_CALL_CB + Z_DELREF_P(retval_ptr_ptr); /* fetch dim addr will increment refcount */ + return retval_ptr_ptr; + } + + if (retval->initialized == 1) { + /* Service has already been called, return its cached value */ + return retval->value; + } + + ALLOC_INIT_ZVAL(retval->raw); + MAKE_COPY_ZVAL(&retval->value, retval->raw); + + PIMPLE_CALL_CB + + retval->initialized = 1; + zval_ptr_dtor(&retval->value); + retval->value = retval_ptr_ptr; + + return retval->value; +} + +static int pimple_zval_is_valid_callback(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC) +{ + if (Z_TYPE_P(_zval) != IS_OBJECT) { + return FAILURE; + } + + if (_pimple_bucket_value->fcc.called_scope) { + return SUCCESS; + } + + if (Z_OBJ_HANDLER_P(_zval, get_closure) && Z_OBJ_HANDLER_P(_zval, get_closure)(_zval, &_pimple_bucket_value->fcc.calling_scope, &_pimple_bucket_value->fcc.function_handler, &_pimple_bucket_value->fcc.object_ptr TSRMLS_CC) == SUCCESS) { + _pimple_bucket_value->fcc.called_scope = _pimple_bucket_value->fcc.calling_scope; + return SUCCESS; + } else { + return FAILURE; + } +} + +static int pimple_zval_to_pimpleval(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC) +{ + _pimple_bucket_value->value = _zval; + + if (Z_TYPE_P(_zval) != IS_OBJECT) { + return PIMPLE_IS_PARAM; + } + + if (pimple_zval_is_valid_callback(_zval, _pimple_bucket_value TSRMLS_CC) == SUCCESS) { + _pimple_bucket_value->type = PIMPLE_IS_SERVICE; + _pimple_bucket_value->handle_num = Z_OBJ_HANDLE_P(_zval); + } + + return PIMPLE_IS_SERVICE; +} + +static void pimple_bucket_dtor(pimple_bucket_value *bucket) +{ + zval_ptr_dtor(&bucket->value); + pimple_free_bucket(bucket); +} + +PHP_METHOD(Pimple, protect) +{ + zval *protected = NULL; + pimple_object *pobj = NULL; + pimple_bucket_value bucket = {0}; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &protected) == FAILURE) { + return; + } + + if (pimple_zval_is_valid_callback(protected, &bucket TSRMLS_CC) == FAILURE) { + pimple_free_bucket(&bucket); + zend_throw_exception(spl_ce_InvalidArgumentException, "Callable is not a Closure or invokable object.", 0 TSRMLS_CC); + return; + } + + pimple_zval_to_pimpleval(protected, &bucket TSRMLS_CC); + pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC); + + if (zend_hash_index_update(&pobj->protected, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) { + Z_ADDREF_P(protected); + RETURN_ZVAL(protected, 1 , 0); + } else { + pimple_free_bucket(&bucket); + } + RETURN_FALSE; +} + +PHP_METHOD(Pimple, raw) +{ + zval *offset = NULL; + pimple_object *pobj = NULL; + pimple_bucket_value *value = NULL; + ulong index; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { + return; + } + + pobj = zend_object_store_get_object(getThis() TSRMLS_CC); + + switch (Z_TYPE_P(offset)) { + case IS_STRING: + if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" is not defined.", Z_STRVAL_P(offset)); + RETURN_NULL(); + } + break; + case IS_DOUBLE: + case IS_BOOL: + case IS_LONG: + if (Z_TYPE_P(offset) == IS_DOUBLE) { + index = (ulong)Z_DVAL_P(offset); + } else { + index = Z_LVAL_P(offset); + } + if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) { + RETURN_NULL(); + } + break; + case IS_NULL: + default: + zend_error(E_WARNING, "Unsupported offset type"); + } + + if (value->raw) { + RETVAL_ZVAL(value->raw, 1, 0); + } else { + RETVAL_ZVAL(value->value, 1, 0); + } +} + +PHP_METHOD(Pimple, extend) +{ + zval *offset = NULL, *callable = NULL, *pimple_closure_obj = NULL; + pimple_bucket_value bucket = {0}, *value = NULL; + pimple_object *pobj = NULL; + pimple_closure_object *pcobj = NULL; + ulong index; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &callable) == FAILURE) { + return; + } + + pobj = zend_object_store_get_object(getThis() TSRMLS_CC); + + switch (Z_TYPE_P(offset)) { + case IS_STRING: + if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" is not defined.", Z_STRVAL_P(offset)); + RETURN_NULL(); + } + if (value->type != PIMPLE_IS_SERVICE) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%s\" does not contain an object definition.", Z_STRVAL_P(offset)); + RETURN_NULL(); + } + break; + case IS_DOUBLE: + case IS_BOOL: + case IS_LONG: + if (Z_TYPE_P(offset) == IS_DOUBLE) { + index = (ulong)Z_DVAL_P(offset); + } else { + index = Z_LVAL_P(offset); + } + if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%ld\" is not defined.", index); + RETURN_NULL(); + } + if (value->type != PIMPLE_IS_SERVICE) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Identifier \"%ld\" does not contain an object definition.", index); + RETURN_NULL(); + } + break; + case IS_NULL: + default: + zend_error(E_WARNING, "Unsupported offset type"); + } + + if (pimple_zval_is_valid_callback(callable, &bucket TSRMLS_CC) == FAILURE) { + pimple_free_bucket(&bucket); + zend_throw_exception(spl_ce_InvalidArgumentException, "Extension service definition is not a Closure or invokable object.", 0 TSRMLS_CC); + RETURN_NULL(); + } + pimple_free_bucket(&bucket); + + ALLOC_INIT_ZVAL(pimple_closure_obj); + object_init_ex(pimple_closure_obj, pimple_closure_ce); + + pcobj = zend_object_store_get_object(pimple_closure_obj TSRMLS_CC); + pcobj->callable = callable; + pcobj->factory = value->value; + Z_ADDREF_P(callable); + Z_ADDREF_P(value->value); + + if (zend_hash_index_exists(&pobj->factories, value->handle_num)) { + pimple_zval_to_pimpleval(pimple_closure_obj, &bucket TSRMLS_CC); + zend_hash_index_del(&pobj->factories, value->handle_num); + zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL); + Z_ADDREF_P(pimple_closure_obj); + } + + pimple_object_write_dimension(getThis(), offset, pimple_closure_obj TSRMLS_CC); + + RETVAL_ZVAL(pimple_closure_obj, 1, 1); +} + +PHP_METHOD(Pimple, keys) +{ + HashPosition pos; + pimple_object *pobj = NULL; + zval **value = NULL; + zval *endval = NULL; + char *str_index = NULL; + int str_len; + ulong num_index; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + pobj = zend_object_store_get_object(getThis() TSRMLS_CC); + array_init_size(return_value, zend_hash_num_elements(&pobj->values)); + + zend_hash_internal_pointer_reset_ex(&pobj->values, &pos); + + while(zend_hash_get_current_data_ex(&pobj->values, (void **)&value, &pos) == SUCCESS) { + MAKE_STD_ZVAL(endval); + switch (zend_hash_get_current_key_ex(&pobj->values, &str_index, (uint *)&str_len, &num_index, 0, &pos)) { + case HASH_KEY_IS_STRING: + ZVAL_STRINGL(endval, str_index, str_len - 1, 1); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL); + break; + case HASH_KEY_IS_LONG: + ZVAL_LONG(endval, num_index); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL); + break; + } + zend_hash_move_forward_ex(&pobj->values, &pos); + } +} + +PHP_METHOD(Pimple, factory) +{ + zval *factory = NULL; + pimple_object *pobj = NULL; + pimple_bucket_value bucket = {0}; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &factory) == FAILURE) { + return; + } + + if (pimple_zval_is_valid_callback(factory, &bucket TSRMLS_CC) == FAILURE) { + pimple_free_bucket(&bucket); + zend_throw_exception(spl_ce_InvalidArgumentException, "Service definition is not a Closure or invokable object.", 0 TSRMLS_CC); + return; + } + + pimple_zval_to_pimpleval(factory, &bucket TSRMLS_CC); + pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC); + + if (zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) { + Z_ADDREF_P(factory); + RETURN_ZVAL(factory, 1 , 0); + } else { + pimple_free_bucket(&bucket); + } + + RETURN_FALSE; +} + +PHP_METHOD(Pimple, offsetSet) +{ + zval *offset = NULL, *value = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &value) == FAILURE) { + return; + } + + pimple_object_write_dimension(getThis(), offset, value TSRMLS_CC); +} + +PHP_METHOD(Pimple, offsetGet) +{ + zval *offset = NULL, *retval = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { + return; + } + + retval = pimple_object_read_dimension(getThis(), offset, 0 TSRMLS_CC); + + RETVAL_ZVAL(retval, 1, 0); +} + +PHP_METHOD(Pimple, offsetUnset) +{ + zval *offset = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { + return; + } + + pimple_object_unset_dimension(getThis(), offset TSRMLS_CC); +} + +PHP_METHOD(Pimple, offsetExists) +{ + zval *offset = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { + return; + } + + RETVAL_BOOL(pimple_object_has_dimension(getThis(), offset, 1 TSRMLS_CC)); +} + +PHP_METHOD(Pimple, register) +{ + zval *provider; + zval **data; + zval *retval = NULL; + zval key; + + HashTable *array = NULL; + HashPosition pos; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|h", &provider, pimple_serviceprovider_ce, &array) == FAILURE) { + return; + } + + RETVAL_ZVAL(getThis(), 1, 0); + + zend_call_method_with_1_params(&provider, Z_OBJCE_P(provider), NULL, "register", &retval, getThis()); + + if (retval) { + zval_ptr_dtor(&retval); + } + + if (!array) { + return; + } + + zend_hash_internal_pointer_reset_ex(array, &pos); + + while(zend_hash_get_current_data_ex(array, (void **)&data, &pos) == SUCCESS) { + zend_hash_get_current_key_zval_ex(array, &key, &pos); + pimple_object_write_dimension(getThis(), &key, *data TSRMLS_CC); + zend_hash_move_forward_ex(array, &pos); + } +} + +PHP_METHOD(Pimple, __construct) +{ + zval *values = NULL, **pData = NULL, offset; + HashPosition pos; + char *str_index = NULL; + zend_uint str_length; + ulong num_index; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &values) == FAILURE || !values) { + return; + } + + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos); + while (zend_hash_has_more_elements_ex(Z_ARRVAL_P(values), &pos) == SUCCESS) { + zend_hash_get_current_data_ex(Z_ARRVAL_P(values), (void **)&pData, &pos); + zend_hash_get_current_key_ex(Z_ARRVAL_P(values), &str_index, &str_length, &num_index, 0, &pos); + INIT_ZVAL(offset); + if (zend_hash_get_current_key_type_ex(Z_ARRVAL_P(values), &pos) == HASH_KEY_IS_LONG) { + ZVAL_LONG(&offset, num_index); + } else { + ZVAL_STRINGL(&offset, str_index, (str_length - 1), 0); + } + pimple_object_write_dimension(getThis(), &offset, *pData TSRMLS_CC); + zend_hash_move_forward_ex(Z_ARRVAL_P(values), &pos); + } +} + +/* + * This is PHP code snippet handling extend()s calls : + + $extended = function ($c) use ($callable, $factory) { + return $callable($factory($c), $c); + }; + + */ +PHP_METHOD(PimpleClosure, invoker) +{ + pimple_closure_object *pcobj = NULL; + zval *arg = NULL, *retval = NULL, *newretval = NULL; + zend_fcall_info fci = {0}; + zval **args[2]; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) { + return; + } + + pcobj = zend_object_store_get_object(getThis() TSRMLS_CC); + + fci.function_name = pcobj->factory; + args[0] = &arg; + zend_fcall_info_argp(&fci TSRMLS_CC, 1, args); + fci.retval_ptr_ptr = &retval; + fci.size = sizeof(fci); + + if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) { + efree(fci.params); + return; /* Should here return default zval */ + } + + efree(fci.params); + memset(&fci, 0, sizeof(fci)); + fci.size = sizeof(fci); + + fci.function_name = pcobj->callable; + args[0] = &retval; + args[1] = &arg; + zend_fcall_info_argp(&fci TSRMLS_CC, 2, args); + fci.retval_ptr_ptr = &newretval; + + if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) { + efree(fci.params); + zval_ptr_dtor(&retval); + return; + } + + efree(fci.params); + zval_ptr_dtor(&retval); + + RETVAL_ZVAL(newretval, 1 ,1); +} + +PHP_MINIT_FUNCTION(pimple) +{ + zend_class_entry tmp_pimple_ce, tmp_pimple_closure_ce, tmp_pimple_serviceprovider_iface_ce; + INIT_NS_CLASS_ENTRY(tmp_pimple_ce, PIMPLE_NS, "Container", pimple_ce_functions); + INIT_NS_CLASS_ENTRY(tmp_pimple_closure_ce, PIMPLE_NS, "ContainerClosure", NULL); + INIT_NS_CLASS_ENTRY(tmp_pimple_serviceprovider_iface_ce, PIMPLE_NS, "ServiceProviderInterface", pimple_serviceprovider_iface_ce_functions); + + tmp_pimple_ce.create_object = pimple_object_create; + tmp_pimple_closure_ce.create_object = pimple_closure_object_create; + + pimple_ce = zend_register_internal_class(&tmp_pimple_ce TSRMLS_CC); + zend_class_implements(pimple_ce TSRMLS_CC, 1, zend_ce_arrayaccess); + + pimple_closure_ce = zend_register_internal_class(&tmp_pimple_closure_ce TSRMLS_CC); + pimple_closure_ce->ce_flags |= ZEND_ACC_FINAL_CLASS; + + pimple_serviceprovider_ce = zend_register_internal_interface(&tmp_pimple_serviceprovider_iface_ce TSRMLS_CC); + + memcpy(&pimple_closure_object_handlers, zend_get_std_object_handlers(), sizeof(*zend_get_std_object_handlers())); + pimple_object_handlers = std_object_handlers; + pimple_closure_object_handlers.get_closure = pimple_closure_get_closure; + + pimple_closure_invoker_function.function_name = "Pimple closure internal invoker"; + pimple_closure_invoker_function.fn_flags |= ZEND_ACC_CLOSURE; + pimple_closure_invoker_function.handler = ZEND_MN(PimpleClosure_invoker); + pimple_closure_invoker_function.num_args = 1; + pimple_closure_invoker_function.required_num_args = 1; + pimple_closure_invoker_function.scope = pimple_closure_ce; + pimple_closure_invoker_function.type = ZEND_INTERNAL_FUNCTION; + pimple_closure_invoker_function.module = &pimple_module_entry; + + return SUCCESS; +} + +PHP_MINFO_FUNCTION(pimple) +{ + php_info_print_table_start(); + php_info_print_table_header(2, "SensioLabs Pimple C support", "enabled"); + php_info_print_table_row(2, "Pimple supported version", PIMPLE_VERSION); + php_info_print_table_end(); + + php_info_print_box_start(0); + php_write((void *)ZEND_STRL("SensioLabs Pimple C support developed by Julien Pauli") TSRMLS_CC); + if (!sapi_module.phpinfo_as_text) { + php_write((void *)ZEND_STRL(sensiolabs_logo) TSRMLS_CC); + } + php_info_print_box_end(); +} + +zend_module_entry pimple_module_entry = { + STANDARD_MODULE_HEADER, + "pimple", + NULL, + PHP_MINIT(pimple), + NULL, + NULL, + NULL, + PHP_MINFO(pimple), + PIMPLE_VERSION, + STANDARD_MODULE_PROPERTIES +}; + +#ifdef COMPILE_DL_PIMPLE +ZEND_GET_MODULE(pimple) +#endif diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/pimple_compat.h b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/pimple_compat.h new file mode 100644 index 000000000000..d234e174d0aa --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/pimple_compat.h @@ -0,0 +1,81 @@ + +/* + * This file is part of Pimple. + * + * Copyright (c) 2014 Fabien Potencier + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef PIMPLE_COMPAT_H_ +#define PIMPLE_COMPAT_H_ + +#include "Zend/zend_extensions.h" /* for ZEND_EXTENSION_API_NO */ + +#define PHP_5_0_X_API_NO 220040412 +#define PHP_5_1_X_API_NO 220051025 +#define PHP_5_2_X_API_NO 220060519 +#define PHP_5_3_X_API_NO 220090626 +#define PHP_5_4_X_API_NO 220100525 +#define PHP_5_5_X_API_NO 220121212 +#define PHP_5_6_X_API_NO 220131226 + +#define IS_PHP_56 ZEND_EXTENSION_API_NO == PHP_5_6_X_API_NO +#define IS_AT_LEAST_PHP_56 ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO + +#define IS_PHP_55 ZEND_EXTENSION_API_NO == PHP_5_5_X_API_NO +#define IS_AT_LEAST_PHP_55 ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO + +#define IS_PHP_54 ZEND_EXTENSION_API_NO == PHP_5_4_X_API_NO +#define IS_AT_LEAST_PHP_54 ZEND_EXTENSION_API_NO >= PHP_5_4_X_API_NO + +#define IS_PHP_53 ZEND_EXTENSION_API_NO == PHP_5_3_X_API_NO +#define IS_AT_LEAST_PHP_53 ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO + +#if IS_PHP_53 +#define object_properties_init(obj, ce) do { \ + zend_hash_copy(obj->properties, &ce->default_properties, zval_copy_property_ctor(ce), NULL, sizeof(zval *)); \ + } while (0); +#endif + +#define ZEND_OBJ_INIT(obj, ce) do { \ + zend_object_std_init(obj, ce TSRMLS_CC); \ + object_properties_init((obj), (ce)); \ + } while(0); + +#if IS_PHP_53 || IS_PHP_54 +static void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos) { + Bucket *p; + + p = pos ? (*pos) : ht->pInternalPointer; + + if (!p) { + Z_TYPE_P(key) = IS_NULL; + } else if (p->nKeyLength) { + Z_TYPE_P(key) = IS_STRING; + Z_STRVAL_P(key) = estrndup(p->arKey, p->nKeyLength - 1); + Z_STRLEN_P(key) = p->nKeyLength - 1; + } else { + Z_TYPE_P(key) = IS_LONG; + Z_LVAL_P(key) = p->h; + } +} +#endif + +#endif /* PIMPLE_COMPAT_H_ */ diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/001.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/001.phpt new file mode 100644 index 000000000000..0809ea232b66 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/001.phpt @@ -0,0 +1,45 @@ +--TEST-- +Test for read_dim/write_dim handlers +--SKIPIF-- + +--FILE-- + + +--EXPECTF-- +foo +42 +foo2 +foo99 +baz +strstr \ No newline at end of file diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/002.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/002.phpt new file mode 100644 index 000000000000..7b56d2c1fe8b --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/002.phpt @@ -0,0 +1,15 @@ +--TEST-- +Test for constructor +--SKIPIF-- + +--FILE-- +'foo')); +var_dump($p[42]); +?> +--EXPECT-- +NULL +string(3) "foo" diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/003.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/003.phpt new file mode 100644 index 000000000000..a22cfa352ea6 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/003.phpt @@ -0,0 +1,16 @@ +--TEST-- +Test empty dimensions +--SKIPIF-- + +--FILE-- + +--EXPECT-- +int(42) +string(3) "bar" \ No newline at end of file diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/004.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/004.phpt new file mode 100644 index 000000000000..1e1d25136792 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/004.phpt @@ -0,0 +1,30 @@ +--TEST-- +Test has/unset dim handlers +--SKIPIF-- + +--FILE-- + +--EXPECT-- +int(42) +NULL +bool(true) +bool(false) +bool(true) +bool(true) \ No newline at end of file diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/005.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/005.phpt new file mode 100644 index 000000000000..0479ee055ded --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/005.phpt @@ -0,0 +1,27 @@ +--TEST-- +Test simple class inheritance +--SKIPIF-- + +--FILE-- +someAttr; +?> +--EXPECT-- +string(3) "hit" +foo +fooAttr \ No newline at end of file diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/006.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/006.phpt new file mode 100644 index 000000000000..cfe8a119e63a --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/006.phpt @@ -0,0 +1,51 @@ +--TEST-- +Test complex class inheritance +--SKIPIF-- + +--FILE-- + 'bar', 88 => 'baz'); + +$p = new TestPimple($defaultValues); +$p[42] = 'foo'; +var_dump($p[42]); +var_dump($p[0]); +?> +--EXPECT-- +string(13) "hit offsetset" +string(27) "hit offsetget in TestPimple" +string(25) "hit offsetget in MyPimple" +string(3) "foo" +string(27) "hit offsetget in TestPimple" +string(25) "hit offsetget in MyPimple" +string(3) "baz" \ No newline at end of file diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/007.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/007.phpt new file mode 100644 index 000000000000..5aac68380643 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/007.phpt @@ -0,0 +1,22 @@ +--TEST-- +Test for read_dim/write_dim handlers +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +foo +42 \ No newline at end of file diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/008.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/008.phpt new file mode 100644 index 000000000000..db7eeec4a113 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/008.phpt @@ -0,0 +1,29 @@ +--TEST-- +Test frozen services +--SKIPIF-- + +--FILE-- + +--EXPECTF-- diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/009.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/009.phpt new file mode 100644 index 000000000000..bb05ea296485 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/009.phpt @@ -0,0 +1,13 @@ +--TEST-- +Test service is called as callback, and only once +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +bool(true) \ No newline at end of file diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/010.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/010.phpt new file mode 100644 index 000000000000..badce0146a91 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/010.phpt @@ -0,0 +1,45 @@ +--TEST-- +Test service is called as callback for every callback type +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +callme +called +Foo::bar +array(2) { + [0]=> + string(3) "Foo" + [1]=> + string(3) "bar" +} \ No newline at end of file diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/011.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/011.phpt new file mode 100644 index 000000000000..6682ab8ebdbc --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/011.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test service callback throwing an exception +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +all right! \ No newline at end of file diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/012.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/012.phpt new file mode 100644 index 000000000000..4c6ac486dc74 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/012.phpt @@ -0,0 +1,28 @@ +--TEST-- +Test service factory +--SKIPIF-- + +--FILE-- +factory($f = function() { var_dump('called-1'); return 'ret-1';}); + +$p[] = $f; + +$p[] = function () { var_dump('called-2'); return 'ret-2'; }; + +var_dump($p[0]); +var_dump($p[0]); +var_dump($p[1]); +var_dump($p[1]); +?> +--EXPECTF-- +string(8) "called-1" +string(5) "ret-1" +string(8) "called-1" +string(5) "ret-1" +string(8) "called-2" +string(5) "ret-2" +string(5) "ret-2" \ No newline at end of file diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/013.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/013.phpt new file mode 100644 index 000000000000..f419958c5fa5 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/013.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test keys() +--SKIPIF-- + +--FILE-- +keys()); + +$p['foo'] = 'bar'; +$p[] = 'foo'; + +var_dump($p->keys()); + +unset($p['foo']); + +var_dump($p->keys()); +?> +--EXPECTF-- +array(0) { +} +array(2) { + [0]=> + string(3) "foo" + [1]=> + int(0) +} +array(1) { + [0]=> + int(0) +} \ No newline at end of file diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/014.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/014.phpt new file mode 100644 index 000000000000..ac937213ac0b --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/014.phpt @@ -0,0 +1,30 @@ +--TEST-- +Test raw() +--SKIPIF-- + +--FILE-- +raw('foo')); +var_dump($p[42]); + +unset($p['foo']); + +try { + $p->raw('foo'); + echo "expected exception"; +} catch (InvalidArgumentException $e) { } +--EXPECTF-- +string(8) "called-2" +string(5) "ret-2" +object(Closure)#%i (0) { +} +string(8) "called-2" +string(5) "ret-2" \ No newline at end of file diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/015.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/015.phpt new file mode 100644 index 000000000000..314f008ac1bb --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/015.phpt @@ -0,0 +1,17 @@ +--TEST-- +Test protect() +--SKIPIF-- + +--FILE-- +protect($f); + +var_dump($p['foo']); +--EXPECTF-- +object(Closure)#%i (0) { +} \ No newline at end of file diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/016.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/016.phpt new file mode 100644 index 000000000000..e55edb0a7a13 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/016.phpt @@ -0,0 +1,24 @@ +--TEST-- +Test extend() +--SKIPIF-- + +--FILE-- +extend(12, function ($w) { var_dump($w); return 'bar'; }); /* $callable in code above */ + +var_dump($c('param')); +--EXPECTF-- +string(5) "param" +string(3) "foo" +string(3) "bar" \ No newline at end of file diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/017.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/017.phpt new file mode 100644 index 000000000000..bac23ce09a91 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/017.phpt @@ -0,0 +1,17 @@ +--TEST-- +Test extend() with exception in service extension +--SKIPIF-- + +--FILE-- +extend(12, function ($w) { throw new BadMethodCallException; }); + +try { + $p[12]; + echo "Exception expected"; +} catch (BadMethodCallException $e) { } +--EXPECTF-- diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt new file mode 100644 index 000000000000..8f881d6ebf82 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt @@ -0,0 +1,17 @@ +--TEST-- +Test extend() with exception in service factory +--SKIPIF-- + +--FILE-- +extend(12, function ($w) { return 'foobar'; }); + +try { + $p[12]; + echo "Exception expected"; +} catch (BadMethodCallException $e) { } +--EXPECTF-- diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/018.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/018.phpt new file mode 100644 index 000000000000..27c12a14e79e --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/018.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test register() +--SKIPIF-- + +--FILE-- +register(new Foo, array(42 => 'bar')); + +var_dump($p[42]); +--EXPECTF-- +object(Pimple\Container)#1 (0) { +} +string(3) "bar" \ No newline at end of file diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/019.phpt b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/019.phpt new file mode 100644 index 000000000000..28a9aecac7f0 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/019.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test register() returns static and is a fluent interface +--SKIPIF-- + +--FILE-- +register(new Foo)); +--EXPECTF-- +bool(true) diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/bench.phpb b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/bench.phpb new file mode 100644 index 000000000000..8f983e656b52 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/bench.phpb @@ -0,0 +1,51 @@ +factory($factory); + +$p['factory'] = $factory; + +echo $p['factory']; +echo $p['factory']; +echo $p['factory']; + +} + +echo microtime(true) - $time; diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb new file mode 100644 index 000000000000..aec541f0bc8b --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb @@ -0,0 +1,25 @@ + diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/phpunit.xml.dist b/samples/server/petstore/slim/vendor/pimple/pimple/phpunit.xml.dist new file mode 100644 index 000000000000..5c8d487fea9a --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/phpunit.xml.dist @@ -0,0 +1,14 @@ + + + + + + ./src/Pimple/Tests + + + diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Container.php b/samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Container.php new file mode 100644 index 000000000000..c976431e99a8 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Container.php @@ -0,0 +1,282 @@ +factories = new \SplObjectStorage(); + $this->protected = new \SplObjectStorage(); + + foreach ($values as $key => $value) { + $this->offsetSet($key, $value); + } + } + + /** + * Sets a parameter or an object. + * + * Objects must be defined as Closures. + * + * Allowing any PHP callable leads to difficult to debug problems + * as function names (strings) are callable (creating a function with + * the same name as an existing parameter would break your container). + * + * @param string $id The unique identifier for the parameter or object + * @param mixed $value The value of the parameter or a closure to define an object + * + * @throws \RuntimeException Prevent override of a frozen service + */ + public function offsetSet($id, $value) + { + if (isset($this->frozen[$id])) { + throw new \RuntimeException(sprintf('Cannot override frozen service "%s".', $id)); + } + + $this->values[$id] = $value; + $this->keys[$id] = true; + } + + /** + * Gets a parameter or an object. + * + * @param string $id The unique identifier for the parameter or object + * + * @return mixed The value of the parameter or an object + * + * @throws \InvalidArgumentException if the identifier is not defined + */ + public function offsetGet($id) + { + if (!isset($this->keys[$id])) { + throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id)); + } + + if ( + isset($this->raw[$id]) + || !is_object($this->values[$id]) + || isset($this->protected[$this->values[$id]]) + || !method_exists($this->values[$id], '__invoke') + ) { + return $this->values[$id]; + } + + if (isset($this->factories[$this->values[$id]])) { + return $this->values[$id]($this); + } + + $raw = $this->values[$id]; + $val = $this->values[$id] = $raw($this); + $this->raw[$id] = $raw; + + $this->frozen[$id] = true; + + return $val; + } + + /** + * Checks if a parameter or an object is set. + * + * @param string $id The unique identifier for the parameter or object + * + * @return bool + */ + public function offsetExists($id) + { + return isset($this->keys[$id]); + } + + /** + * Unsets a parameter or an object. + * + * @param string $id The unique identifier for the parameter or object + */ + public function offsetUnset($id) + { + if (isset($this->keys[$id])) { + if (is_object($this->values[$id])) { + unset($this->factories[$this->values[$id]], $this->protected[$this->values[$id]]); + } + + unset($this->values[$id], $this->frozen[$id], $this->raw[$id], $this->keys[$id]); + } + } + + /** + * Marks a callable as being a factory service. + * + * @param callable $callable A service definition to be used as a factory + * + * @return callable The passed callable + * + * @throws \InvalidArgumentException Service definition has to be a closure of an invokable object + */ + public function factory($callable) + { + if (!method_exists($callable, '__invoke')) { + throw new \InvalidArgumentException('Service definition is not a Closure or invokable object.'); + } + + $this->factories->attach($callable); + + return $callable; + } + + /** + * Protects a callable from being interpreted as a service. + * + * This is useful when you want to store a callable as a parameter. + * + * @param callable $callable A callable to protect from being evaluated + * + * @return callable The passed callable + * + * @throws \InvalidArgumentException Service definition has to be a closure of an invokable object + */ + public function protect($callable) + { + if (!method_exists($callable, '__invoke')) { + throw new \InvalidArgumentException('Callable is not a Closure or invokable object.'); + } + + $this->protected->attach($callable); + + return $callable; + } + + /** + * Gets a parameter or the closure defining an object. + * + * @param string $id The unique identifier for the parameter or object + * + * @return mixed The value of the parameter or the closure defining an object + * + * @throws \InvalidArgumentException if the identifier is not defined + */ + public function raw($id) + { + if (!isset($this->keys[$id])) { + throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id)); + } + + if (isset($this->raw[$id])) { + return $this->raw[$id]; + } + + return $this->values[$id]; + } + + /** + * Extends an object definition. + * + * Useful when you want to extend an existing object definition, + * without necessarily loading that object. + * + * @param string $id The unique identifier for the object + * @param callable $callable A service definition to extend the original + * + * @return callable The wrapped callable + * + * @throws \InvalidArgumentException if the identifier is not defined or not a service definition + */ + public function extend($id, $callable) + { + if (!isset($this->keys[$id])) { + throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id)); + } + + if (!is_object($this->values[$id]) || !method_exists($this->values[$id], '__invoke')) { + throw new \InvalidArgumentException(sprintf('Identifier "%s" does not contain an object definition.', $id)); + } + + if (!is_object($callable) || !method_exists($callable, '__invoke')) { + throw new \InvalidArgumentException('Extension service definition is not a Closure or invokable object.'); + } + + $factory = $this->values[$id]; + + $extended = function ($c) use ($callable, $factory) { + return $callable($factory($c), $c); + }; + + if (isset($this->factories[$factory])) { + $this->factories->detach($factory); + $this->factories->attach($extended); + } + + return $this[$id] = $extended; + } + + /** + * Returns all defined value names. + * + * @return array An array of value names + */ + public function keys() + { + return array_keys($this->values); + } + + /** + * Registers a service provider. + * + * @param ServiceProviderInterface $provider A ServiceProviderInterface instance + * @param array $values An array of values that customizes the provider + * + * @return static + */ + public function register(ServiceProviderInterface $provider, array $values = array()) + { + $provider->register($this); + + foreach ($values as $key => $value) { + $this[$key] = $value; + } + + return $this; + } +} diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php b/samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php new file mode 100644 index 000000000000..c004594baf04 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php @@ -0,0 +1,46 @@ +value = $value; + + return $service; + } +} diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php b/samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php new file mode 100644 index 000000000000..33cd4e548640 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php @@ -0,0 +1,34 @@ +factory(function () { + return new Service(); + }); + } +} diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php b/samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php new file mode 100644 index 000000000000..d71b184ddf7f --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php @@ -0,0 +1,35 @@ + + */ +class Service +{ + public $value; +} diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php b/samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php new file mode 100644 index 000000000000..8e5c4c73deb0 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php @@ -0,0 +1,76 @@ + + */ +class PimpleServiceProviderInterfaceTest extends \PHPUnit_Framework_TestCase +{ + public function testProvider() + { + $pimple = new Container(); + + $pimpleServiceProvider = new Fixtures\PimpleServiceProvider(); + $pimpleServiceProvider->register($pimple); + + $this->assertEquals('value', $pimple['param']); + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); + + $serviceOne = $pimple['factory']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + + $serviceTwo = $pimple['factory']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + + $this->assertNotSame($serviceOne, $serviceTwo); + } + + public function testProviderWithRegisterMethod() + { + $pimple = new Container(); + + $pimple->register(new Fixtures\PimpleServiceProvider(), array( + 'anotherParameter' => 'anotherValue', + )); + + $this->assertEquals('value', $pimple['param']); + $this->assertEquals('anotherValue', $pimple['anotherParameter']); + + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); + + $serviceOne = $pimple['factory']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + + $serviceTwo = $pimple['factory']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + + $this->assertNotSame($serviceOne, $serviceTwo); + } +} diff --git a/samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php b/samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php new file mode 100644 index 000000000000..918f620d8841 --- /dev/null +++ b/samples/server/petstore/slim/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php @@ -0,0 +1,440 @@ + + */ +class PimpleTest extends \PHPUnit_Framework_TestCase +{ + public function testWithString() + { + $pimple = new Container(); + $pimple['param'] = 'value'; + + $this->assertEquals('value', $pimple['param']); + } + + public function testWithClosure() + { + $pimple = new Container(); + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); + } + + public function testServicesShouldBeDifferent() + { + $pimple = new Container(); + $pimple['service'] = $pimple->factory(function () { + return new Fixtures\Service(); + }); + + $serviceOne = $pimple['service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + + $serviceTwo = $pimple['service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + + $this->assertNotSame($serviceOne, $serviceTwo); + } + + public function testShouldPassContainerAsParameter() + { + $pimple = new Container(); + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + $pimple['container'] = function ($container) { + return $container; + }; + + $this->assertNotSame($pimple, $pimple['service']); + $this->assertSame($pimple, $pimple['container']); + } + + public function testIsset() + { + $pimple = new Container(); + $pimple['param'] = 'value'; + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + + $pimple['null'] = null; + + $this->assertTrue(isset($pimple['param'])); + $this->assertTrue(isset($pimple['service'])); + $this->assertTrue(isset($pimple['null'])); + $this->assertFalse(isset($pimple['non_existent'])); + } + + public function testConstructorInjection() + { + $params = array('param' => 'value'); + $pimple = new Container($params); + + $this->assertSame($params['param'], $pimple['param']); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Identifier "foo" is not defined. + */ + public function testOffsetGetValidatesKeyIsPresent() + { + $pimple = new Container(); + echo $pimple['foo']; + } + + public function testOffsetGetHonorsNullValues() + { + $pimple = new Container(); + $pimple['foo'] = null; + $this->assertNull($pimple['foo']); + } + + public function testUnset() + { + $pimple = new Container(); + $pimple['param'] = 'value'; + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + + unset($pimple['param'], $pimple['service']); + $this->assertFalse(isset($pimple['param'])); + $this->assertFalse(isset($pimple['service'])); + } + + /** + * @dataProvider serviceDefinitionProvider + */ + public function testShare($service) + { + $pimple = new Container(); + $pimple['shared_service'] = $service; + + $serviceOne = $pimple['shared_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + + $serviceTwo = $pimple['shared_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + + $this->assertSame($serviceOne, $serviceTwo); + } + + /** + * @dataProvider serviceDefinitionProvider + */ + public function testProtect($service) + { + $pimple = new Container(); + $pimple['protected'] = $pimple->protect($service); + + $this->assertSame($service, $pimple['protected']); + } + + public function testGlobalFunctionNameAsParameterValue() + { + $pimple = new Container(); + $pimple['global_function'] = 'strlen'; + $this->assertSame('strlen', $pimple['global_function']); + } + + public function testRaw() + { + $pimple = new Container(); + $pimple['service'] = $definition = $pimple->factory(function () { return 'foo'; }); + $this->assertSame($definition, $pimple->raw('service')); + } + + public function testRawHonorsNullValues() + { + $pimple = new Container(); + $pimple['foo'] = null; + $this->assertNull($pimple->raw('foo')); + } + + public function testFluentRegister() + { + $pimple = new Container(); + $this->assertSame($pimple, $pimple->register($this->getMock('Pimple\ServiceProviderInterface'))); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Identifier "foo" is not defined. + */ + public function testRawValidatesKeyIsPresent() + { + $pimple = new Container(); + $pimple->raw('foo'); + } + + /** + * @dataProvider serviceDefinitionProvider + */ + public function testExtend($service) + { + $pimple = new Container(); + $pimple['shared_service'] = function () { + return new Fixtures\Service(); + }; + $pimple['factory_service'] = $pimple->factory(function () { + return new Fixtures\Service(); + }); + + $pimple->extend('shared_service', $service); + $serviceOne = $pimple['shared_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + $serviceTwo = $pimple['shared_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + $this->assertSame($serviceOne, $serviceTwo); + $this->assertSame($serviceOne->value, $serviceTwo->value); + + $pimple->extend('factory_service', $service); + $serviceOne = $pimple['factory_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + $serviceTwo = $pimple['factory_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + $this->assertNotSame($serviceOne, $serviceTwo); + $this->assertNotSame($serviceOne->value, $serviceTwo->value); + } + + public function testExtendDoesNotLeakWithFactories() + { + if (extension_loaded('pimple')) { + $this->markTestSkipped('Pimple extension does not support this test'); + } + $pimple = new Container(); + + $pimple['foo'] = $pimple->factory(function () { return; }); + $pimple['foo'] = $pimple->extend('foo', function ($foo, $pimple) { return; }); + unset($pimple['foo']); + + $p = new \ReflectionProperty($pimple, 'values'); + $p->setAccessible(true); + $this->assertEmpty($p->getValue($pimple)); + + $p = new \ReflectionProperty($pimple, 'factories'); + $p->setAccessible(true); + $this->assertCount(0, $p->getValue($pimple)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Identifier "foo" is not defined. + */ + public function testExtendValidatesKeyIsPresent() + { + $pimple = new Container(); + $pimple->extend('foo', function () {}); + } + + public function testKeys() + { + $pimple = new Container(); + $pimple['foo'] = 123; + $pimple['bar'] = 123; + + $this->assertEquals(array('foo', 'bar'), $pimple->keys()); + } + + /** @test */ + public function settingAnInvokableObjectShouldTreatItAsFactory() + { + $pimple = new Container(); + $pimple['invokable'] = new Fixtures\Invokable(); + + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['invokable']); + } + + /** @test */ + public function settingNonInvokableObjectShouldTreatItAsParameter() + { + $pimple = new Container(); + $pimple['non_invokable'] = new Fixtures\NonInvokable(); + + $this->assertInstanceOf('Pimple\Tests\Fixtures\NonInvokable', $pimple['non_invokable']); + } + + /** + * @dataProvider badServiceDefinitionProvider + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Service definition is not a Closure or invokable object. + */ + public function testFactoryFailsForInvalidServiceDefinitions($service) + { + $pimple = new Container(); + $pimple->factory($service); + } + + /** + * @dataProvider badServiceDefinitionProvider + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Callable is not a Closure or invokable object. + */ + public function testProtectFailsForInvalidServiceDefinitions($service) + { + $pimple = new Container(); + $pimple->protect($service); + } + + /** + * @dataProvider badServiceDefinitionProvider + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Identifier "foo" does not contain an object definition. + */ + public function testExtendFailsForKeysNotContainingServiceDefinitions($service) + { + $pimple = new Container(); + $pimple['foo'] = $service; + $pimple->extend('foo', function () {}); + } + + /** + * @dataProvider badServiceDefinitionProvider + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Extension service definition is not a Closure or invokable object. + */ + public function testExtendFailsForInvalidServiceDefinitions($service) + { + $pimple = new Container(); + $pimple['foo'] = function () {}; + $pimple->extend('foo', $service); + } + + /** + * Provider for invalid service definitions. + */ + public function badServiceDefinitionProvider() + { + return array( + array(123), + array(new Fixtures\NonInvokable()), + ); + } + + /** + * Provider for service definitions. + */ + public function serviceDefinitionProvider() + { + return array( + array(function ($value) { + $service = new Fixtures\Service(); + $service->value = $value; + + return $service; + }), + array(new Fixtures\Invokable()), + ); + } + + public function testDefiningNewServiceAfterFreeze() + { + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $foo = $pimple['foo']; + + $pimple['bar'] = function () { + return 'bar'; + }; + $this->assertSame('bar', $pimple['bar']); + } + + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage Cannot override frozen service "foo". + */ + public function testOverridingServiceAfterFreeze() + { + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $foo = $pimple['foo']; + + $pimple['foo'] = function () { + return 'bar'; + }; + } + + public function testRemovingServiceAfterFreeze() + { + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $foo = $pimple['foo']; + + unset($pimple['foo']); + $pimple['foo'] = function () { + return 'bar'; + }; + $this->assertSame('bar', $pimple['foo']); + } + + public function testExtendingService() + { + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) { + return "$foo.bar"; + }); + $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) { + return "$foo.baz"; + }); + $this->assertSame('foo.bar.baz', $pimple['foo']); + } + + public function testExtendingServiceAfterOtherServiceFreeze() + { + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $pimple['bar'] = function () { + return 'bar'; + }; + $foo = $pimple['foo']; + + $pimple['bar'] = $pimple->extend('bar', function ($bar, $app) { + return "$bar.baz"; + }); + $this->assertSame('bar.baz', $pimple['bar']); + } +} diff --git a/samples/server/petstore/slim/vendor/psr/http-message/LICENSE b/samples/server/petstore/slim/vendor/psr/http-message/LICENSE new file mode 100644 index 000000000000..c2d8e452de1b --- /dev/null +++ b/samples/server/petstore/slim/vendor/psr/http-message/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014 PHP Framework Interoperability Group + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/samples/server/petstore/slim/vendor/psr/http-message/README.md b/samples/server/petstore/slim/vendor/psr/http-message/README.md new file mode 100644 index 000000000000..28185338f723 --- /dev/null +++ b/samples/server/petstore/slim/vendor/psr/http-message/README.md @@ -0,0 +1,13 @@ +PSR Http Message +================ + +This repository holds all interfaces/classes/traits related to +[PSR-7](http://www.php-fig.org/psr/psr-7/). + +Note that this is not a HTTP message implementation of its own. It is merely an +interface that describes a HTTP message. See the specification for more details. + +Usage +----- + +We'll certainly need some stuff in here. \ No newline at end of file diff --git a/samples/server/petstore/slim/vendor/psr/http-message/composer.json b/samples/server/petstore/slim/vendor/psr/http-message/composer.json new file mode 100644 index 000000000000..4774b6126276 --- /dev/null +++ b/samples/server/petstore/slim/vendor/psr/http-message/composer.json @@ -0,0 +1,25 @@ +{ + "name": "psr/http-message", + "description": "Common interface for HTTP messages", + "keywords": ["psr", "psr-7", "http", "http-message", "request", "response"], + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "require": { + "php": ">=5.3.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/samples/server/petstore/slim/vendor/psr/http-message/src/MessageInterface.php b/samples/server/petstore/slim/vendor/psr/http-message/src/MessageInterface.php new file mode 100644 index 000000000000..8f67a050e8cf --- /dev/null +++ b/samples/server/petstore/slim/vendor/psr/http-message/src/MessageInterface.php @@ -0,0 +1,187 @@ +getHeaders() as $name => $values) { + * echo $name . ": " . implode(", ", $values); + * } + * + * // Emit headers iteratively: + * foreach ($message->getHeaders() as $name => $values) { + * foreach ($values as $value) { + * header(sprintf('%s: %s', $name, $value), false); + * } + * } + * + * While header names are not case-sensitive, getHeaders() will preserve the + * exact case in which headers were originally specified. + * + * @return array Returns an associative array of the message's headers. Each + * key MUST be a header name, and each value MUST be an array of strings + * for that header. + */ + public function getHeaders(); + + /** + * Checks if a header exists by the given case-insensitive name. + * + * @param string $name Case-insensitive header field name. + * @return bool Returns true if any header names match the given header + * name using a case-insensitive string comparison. Returns false if + * no matching header name is found in the message. + */ + public function hasHeader($name); + + /** + * Retrieves a message header value by the given case-insensitive name. + * + * This method returns an array of all the header values of the given + * case-insensitive header name. + * + * If the header does not appear in the message, this method MUST return an + * empty array. + * + * @param string $name Case-insensitive header field name. + * @return string[] An array of string values as provided for the given + * header. If the header does not appear in the message, this method MUST + * return an empty array. + */ + public function getHeader($name); + + /** + * Retrieves a comma-separated string of the values for a single header. + * + * This method returns all of the header values of the given + * case-insensitive header name as a string concatenated together using + * a comma. + * + * NOTE: Not all header values may be appropriately represented using + * comma concatenation. For such headers, use getHeader() instead + * and supply your own delimiter when concatenating. + * + * If the header does not appear in the message, this method MUST return + * an empty string. + * + * @param string $name Case-insensitive header field name. + * @return string A string of values as provided for the given header + * concatenated together using a comma. If the header does not appear in + * the message, this method MUST return an empty string. + */ + public function getHeaderLine($name); + + /** + * Return an instance with the provided value replacing the specified header. + * + * While header names are case-insensitive, the casing of the header will + * be preserved by this function, and returned from getHeaders(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new and/or updated header and value. + * + * @param string $name Case-insensitive header field name. + * @param string|string[] $value Header value(s). + * @return self + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withHeader($name, $value); + + /** + * Return an instance with the specified header appended with the given value. + * + * Existing values for the specified header will be maintained. The new + * value(s) will be appended to the existing list. If the header did not + * exist previously, it will be added. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new header and/or value. + * + * @param string $name Case-insensitive header field name to add. + * @param string|string[] $value Header value(s). + * @return self + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withAddedHeader($name, $value); + + /** + * Return an instance without the specified header. + * + * Header resolution MUST be done without case-sensitivity. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the named header. + * + * @param string $name Case-insensitive header field name to remove. + * @return self + */ + public function withoutHeader($name); + + /** + * Gets the body of the message. + * + * @return StreamInterface Returns the body as a stream. + */ + public function getBody(); + + /** + * Return an instance with the specified message body. + * + * The body MUST be a StreamInterface object. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return a new instance that has the + * new body stream. + * + * @param StreamInterface $body Body. + * @return self + * @throws \InvalidArgumentException When the body is not valid. + */ + public function withBody(StreamInterface $body); +} diff --git a/samples/server/petstore/slim/vendor/psr/http-message/src/RequestInterface.php b/samples/server/petstore/slim/vendor/psr/http-message/src/RequestInterface.php new file mode 100644 index 000000000000..75c802e2927d --- /dev/null +++ b/samples/server/petstore/slim/vendor/psr/http-message/src/RequestInterface.php @@ -0,0 +1,129 @@ +getQuery()` + * or from the `QUERY_STRING` server param. + * + * @return array + */ + public function getQueryParams(); + + /** + * Return an instance with the specified query string arguments. + * + * These values SHOULD remain immutable over the course of the incoming + * request. They MAY be injected during instantiation, such as from PHP's + * $_GET superglobal, or MAY be derived from some other value such as the + * URI. In cases where the arguments are parsed from the URI, the data + * MUST be compatible with what PHP's parse_str() would return for + * purposes of how duplicate query parameters are handled, and how nested + * sets are handled. + * + * Setting query string arguments MUST NOT change the URI stored by the + * request, nor the values in the server params. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated query string arguments. + * + * @param array $query Array of query string arguments, typically from + * $_GET. + * @return self + */ + public function withQueryParams(array $query); + + /** + * Retrieve normalized file upload data. + * + * This method returns upload metadata in a normalized tree, with each leaf + * an instance of Psr\Http\Message\UploadedFileInterface. + * + * These values MAY be prepared from $_FILES or the message body during + * instantiation, or MAY be injected via withUploadedFiles(). + * + * @return array An array tree of UploadedFileInterface instances; an empty + * array MUST be returned if no data is present. + */ + public function getUploadedFiles(); + + /** + * Create a new instance with the specified uploaded files. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param array An array tree of UploadedFileInterface instances. + * @return self + * @throws \InvalidArgumentException if an invalid structure is provided. + */ + public function withUploadedFiles(array $uploadedFiles); + + /** + * Retrieve any parameters provided in the request body. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, this method MUST + * return the contents of $_POST. + * + * Otherwise, this method may return any results of deserializing + * the request body content; as parsing returns structured content, the + * potential types MUST be arrays or objects only. A null value indicates + * the absence of body content. + * + * @return null|array|object The deserialized body parameters, if any. + * These will typically be an array or object. + */ + public function getParsedBody(); + + /** + * Return an instance with the specified body parameters. + * + * These MAY be injected during instantiation. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, use this method + * ONLY to inject the contents of $_POST. + * + * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of + * deserializing the request body content. Deserialization/parsing returns + * structured data, and, as such, this method ONLY accepts arrays or objects, + * or a null value if nothing was available to parse. + * + * As an example, if content negotiation determines that the request data + * is a JSON payload, this method could be used to create a request + * instance with the deserialized parameters. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param null|array|object $data The deserialized body data. This will + * typically be in an array or object. + * @return self + * @throws \InvalidArgumentException if an unsupported argument type is + * provided. + */ + public function withParsedBody($data); + + /** + * Retrieve attributes derived from the request. + * + * The request "attributes" may be used to allow injection of any + * parameters derived from the request: e.g., the results of path + * match operations; the results of decrypting cookies; the results of + * deserializing non-form-encoded message bodies; etc. Attributes + * will be application and request specific, and CAN be mutable. + * + * @return array Attributes derived from the request. + */ + public function getAttributes(); + + /** + * Retrieve a single derived request attribute. + * + * Retrieves a single derived request attribute as described in + * getAttributes(). If the attribute has not been previously set, returns + * the default value as provided. + * + * This method obviates the need for a hasAttribute() method, as it allows + * specifying a default value to return if the attribute is not found. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $default Default value to return if the attribute does not exist. + * @return mixed + */ + public function getAttribute($name, $default = null); + + /** + * Return an instance with the specified derived request attribute. + * + * This method allows setting a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $value The value of the attribute. + * @return self + */ + public function withAttribute($name, $value); + + /** + * Return an instance that removes the specified derived request attribute. + * + * This method allows removing a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @return self + */ + public function withoutAttribute($name); +} diff --git a/samples/server/petstore/slim/vendor/psr/http-message/src/StreamInterface.php b/samples/server/petstore/slim/vendor/psr/http-message/src/StreamInterface.php new file mode 100644 index 000000000000..f68f391269b4 --- /dev/null +++ b/samples/server/petstore/slim/vendor/psr/http-message/src/StreamInterface.php @@ -0,0 +1,158 @@ + + * [user-info@]host[:port] + * + * + * If the port component is not set or is the standard port for the current + * scheme, it SHOULD NOT be included. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.2 + * @return string The URI authority, in "[user-info@]host[:port]" format. + */ + public function getAuthority(); + + /** + * Retrieve the user information component of the URI. + * + * If no user information is present, this method MUST return an empty + * string. + * + * If a user is present in the URI, this will return that value; + * additionally, if the password is also present, it will be appended to the + * user value, with a colon (":") separating the values. + * + * The trailing "@" character is not part of the user information and MUST + * NOT be added. + * + * @return string The URI user information, in "username[:password]" format. + */ + public function getUserInfo(); + + /** + * Retrieve the host component of the URI. + * + * If no host is present, this method MUST return an empty string. + * + * The value returned MUST be normalized to lowercase, per RFC 3986 + * Section 3.2.2. + * + * @see http://tools.ietf.org/html/rfc3986#section-3.2.2 + * @return string The URI host. + */ + public function getHost(); + + /** + * Retrieve the port component of the URI. + * + * If a port is present, and it is non-standard for the current scheme, + * this method MUST return it as an integer. If the port is the standard port + * used with the current scheme, this method SHOULD return null. + * + * If no port is present, and no scheme is present, this method MUST return + * a null value. + * + * If no port is present, but a scheme is present, this method MAY return + * the standard port for that scheme, but SHOULD return null. + * + * @return null|int The URI port. + */ + public function getPort(); + + /** + * Retrieve the path component of the URI. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * Normally, the empty path "" and absolute path "/" are considered equal as + * defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically + * do this normalization because in contexts with a trimmed base path, e.g. + * the front controller, this difference becomes significant. It's the task + * of the user to handle both "" and "/". + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.3. + * + * As an example, if the value should include a slash ("/") not intended as + * delimiter between path segments, that value MUST be passed in encoded + * form (e.g., "%2F") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.3 + * @return string The URI path. + */ + public function getPath(); + + /** + * Retrieve the query string of the URI. + * + * If no query string is present, this method MUST return an empty string. + * + * The leading "?" character is not part of the query and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.4. + * + * As an example, if a value in a key/value pair of the query string should + * include an ampersand ("&") not intended as a delimiter between values, + * that value MUST be passed in encoded form (e.g., "%26") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.4 + * @return string The URI query string. + */ + public function getQuery(); + + /** + * Retrieve the fragment component of the URI. + * + * If no fragment is present, this method MUST return an empty string. + * + * The leading "#" character is not part of the fragment and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.5. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.5 + * @return string The URI fragment. + */ + public function getFragment(); + + /** + * Return an instance with the specified scheme. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified scheme. + * + * Implementations MUST support the schemes "http" and "https" case + * insensitively, and MAY accommodate other schemes if required. + * + * An empty scheme is equivalent to removing the scheme. + * + * @param string $scheme The scheme to use with the new instance. + * @return self A new instance with the specified scheme. + * @throws \InvalidArgumentException for invalid or unsupported schemes. + */ + public function withScheme($scheme); + + /** + * Return an instance with the specified user information. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified user information. + * + * Password is optional, but the user information MUST include the + * user; an empty string for the user is equivalent to removing user + * information. + * + * @param string $user The user name to use for authority. + * @param null|string $password The password associated with $user. + * @return self A new instance with the specified user information. + */ + public function withUserInfo($user, $password = null); + + /** + * Return an instance with the specified host. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified host. + * + * An empty host value is equivalent to removing the host. + * + * @param string $host The hostname to use with the new instance. + * @return self A new instance with the specified host. + * @throws \InvalidArgumentException for invalid hostnames. + */ + public function withHost($host); + + /** + * Return an instance with the specified port. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified port. + * + * Implementations MUST raise an exception for ports outside the + * established TCP and UDP port ranges. + * + * A null value provided for the port is equivalent to removing the port + * information. + * + * @param null|int $port The port to use with the new instance; a null value + * removes the port information. + * @return self A new instance with the specified port. + * @throws \InvalidArgumentException for invalid ports. + */ + public function withPort($port); + + /** + * Return an instance with the specified path. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified path. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * If the path is intended to be domain-relative rather than path relative then + * it must begin with a slash ("/"). Paths not starting with a slash ("/") + * are assumed to be relative to some base path known to the application or + * consumer. + * + * Users can provide both encoded and decoded path characters. + * Implementations ensure the correct encoding as outlined in getPath(). + * + * @param string $path The path to use with the new instance. + * @return self A new instance with the specified path. + * @throws \InvalidArgumentException for invalid paths. + */ + public function withPath($path); + + /** + * Return an instance with the specified query string. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified query string. + * + * Users can provide both encoded and decoded query characters. + * Implementations ensure the correct encoding as outlined in getQuery(). + * + * An empty query string value is equivalent to removing the query string. + * + * @param string $query The query string to use with the new instance. + * @return self A new instance with the specified query string. + * @throws \InvalidArgumentException for invalid query strings. + */ + public function withQuery($query); + + /** + * Return an instance with the specified URI fragment. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified URI fragment. + * + * Users can provide both encoded and decoded fragment characters. + * Implementations ensure the correct encoding as outlined in getFragment(). + * + * An empty fragment value is equivalent to removing the fragment. + * + * @param string $fragment The fragment to use with the new instance. + * @return self A new instance with the specified fragment. + */ + public function withFragment($fragment); + + /** + * Return the string representation as a URI reference. + * + * Depending on which components of the URI are present, the resulting + * string is either a full URI or relative reference according to RFC 3986, + * Section 4.1. The method concatenates the various components of the URI, + * using the appropriate delimiters: + * + * - If a scheme is present, it MUST be suffixed by ":". + * - If an authority is present, it MUST be prefixed by "//". + * - The path can be concatenated without delimiters. But there are two + * cases where the path has to be adjusted to make the URI reference + * valid as PHP does not allow to throw an exception in __toString(): + * - If the path is rootless and an authority is present, the path MUST + * be prefixed by "/". + * - If the path is starting with more than one "/" and no authority is + * present, the starting slashes MUST be reduced to one. + * - If a query is present, it MUST be prefixed by "?". + * - If a fragment is present, it MUST be prefixed by "#". + * + * @see http://tools.ietf.org/html/rfc3986#section-4.1 + * @return string + */ + public function __toString(); +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/CONTRIBUTING.md b/samples/server/petstore/slim/vendor/slim/slim/CONTRIBUTING.md new file mode 100644 index 000000000000..9bbb6b17ca2c --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/CONTRIBUTING.md @@ -0,0 +1,20 @@ +# How to Contribute + +## Pull Requests + +1. Fork the Slim Framework repository +2. Create a new branch for each feature or improvement +3. Send a pull request from each feature branch to the **develop** branch + +It is very important to separate new features or improvements into separate feature branches, and to send a +pull request for each branch. This allows me to review and pull in new features or improvements individually. + +## Style Guide + +All pull requests must adhere to the [PSR-2 standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md). + +## Unit Testing + +All pull requests must be accompanied by passing unit tests and complete code coverage. The Slim Framework uses phpunit for testing. + +[Learn about PHPUnit](https://github.com/sebastianbergmann/phpunit/) diff --git a/samples/server/petstore/slim/vendor/slim/slim/LICENSE.md b/samples/server/petstore/slim/vendor/slim/slim/LICENSE.md new file mode 100644 index 000000000000..0875f84f9057 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/LICENSE.md @@ -0,0 +1,19 @@ +Copyright (c) 2011-2016 Josh Lockhart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/samples/server/petstore/slim/vendor/slim/slim/README.md b/samples/server/petstore/slim/vendor/slim/slim/README.md new file mode 100644 index 000000000000..d20f3939d1c4 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/README.md @@ -0,0 +1,84 @@ +# Slim Framework + +[![Build Status](https://travis-ci.org/slimphp/Slim.svg?branch=develop)](https://travis-ci.org/slimphp/Slim) +[![Coverage Status](https://coveralls.io/repos/slimphp/Slim/badge.svg)](https://coveralls.io/r/slimphp/Slim) +[![Total Downloads](https://poser.pugx.org/slim/slim/downloads)](https://packagist.org/packages/slim/slim) +[![License](https://poser.pugx.org/slim/slim/license)](https://packagist.org/packages/slim/slim) + +Slim is a PHP micro-framework that helps you quickly write simple yet powerful web applications and APIs. + +## Installation + +It's recommended that you use [Composer](https://getcomposer.org/) to install Slim. + +```bash +$ composer require slim/slim "^3.0" +``` + +This will install Slim and all required dependencies. Slim requires PHP 5.5.0 or newer. + +## Usage + +Create an index.php file with the following contents: + +```php +get('/hello/{name}', function ($request, $response, $args) { + $response->write("Hello, " . $args['name']); + return $response; +}); + +$app->run(); +``` + +You may quickly test this using the built-in PHP server: +```bash +$ php -S localhost:8000 +``` + +Going to http://localhost:8000/hello/world will now display "Hello, world". + +For more information on how to configure your web server, see the [Documentation](http://www.slimframework.com/docs/start/web-servers.html). + +## Tests + +To execute the test suite, you'll need phpunit. + +```bash +$ phpunit +``` + +## Contributing + +Please see [CONTRIBUTING](CONTRIBUTING.md) for details. + +## Learn More + +Learn more at these links: + +- [Website](http://www.slimframework.com) +- [Documentation](http://www.slimframework.com/docs/start/installation.html) +- [Support Forum](http://help.slimframework.com) +- [Twitter](https://twitter.com/slimphp) +- [Resources](https://github.com/xssc/awesome-slim) + +## Security + +If you discover security related issues, please email security@slimframework.com instead of using the issue tracker. + +## Credits + +- [Josh Lockhart](https://github.com/codeguy) +- [Andrew Smith](https://github.com/silentworks) +- [Rob Allen](https://github.com/akrabat) +- [Gabriel Manricks](https://github.com/gmanricks) +- [All Contributors](../../contributors) + +## License + +The Slim Framework is licensed under the MIT license. See [License File](LICENSE.md) for more information. diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/App.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/App.php new file mode 100644 index 000000000000..96d82cb81fb4 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/App.php @@ -0,0 +1,644 @@ +container = $container; + } + + /** + * Enable access to the DI container by consumers of $app + * + * @return ContainerInterface + */ + public function getContainer() + { + return $this->container; + } + + /** + * Add middleware + * + * This method prepends new middleware to the app's middleware stack. + * + * @param callable|string $callable The callback routine + * + * @return static + */ + public function add($callable) + { + return $this->addMiddleware(new DeferredCallable($callable, $this->container)); + } + + /** + * Calling a non-existant method on App checks to see if there's an item + * in the container that is callable and if so, calls it. + * + * @param string $method + * @param array $args + * @return mixed + */ + public function __call($method, $args) + { + if ($this->container->has($method)) { + $obj = $this->container->get($method); + if (is_callable($obj)) { + return call_user_func_array($obj, $args); + } + } + + throw new \BadMethodCallException("Method $method is not a valid method"); + } + + /******************************************************************************** + * Router proxy methods + *******************************************************************************/ + + /** + * Add GET route + * + * @param string $pattern The route URI pattern + * @param callable|string $callable The route callback routine + * + * @return \Slim\Interfaces\RouteInterface + */ + public function get($pattern, $callable) + { + return $this->map(['GET'], $pattern, $callable); + } + + /** + * Add POST route + * + * @param string $pattern The route URI pattern + * @param callable|string $callable The route callback routine + * + * @return \Slim\Interfaces\RouteInterface + */ + public function post($pattern, $callable) + { + return $this->map(['POST'], $pattern, $callable); + } + + /** + * Add PUT route + * + * @param string $pattern The route URI pattern + * @param callable|string $callable The route callback routine + * + * @return \Slim\Interfaces\RouteInterface + */ + public function put($pattern, $callable) + { + return $this->map(['PUT'], $pattern, $callable); + } + + /** + * Add PATCH route + * + * @param string $pattern The route URI pattern + * @param callable|string $callable The route callback routine + * + * @return \Slim\Interfaces\RouteInterface + */ + public function patch($pattern, $callable) + { + return $this->map(['PATCH'], $pattern, $callable); + } + + /** + * Add DELETE route + * + * @param string $pattern The route URI pattern + * @param callable|string $callable The route callback routine + * + * @return \Slim\Interfaces\RouteInterface + */ + public function delete($pattern, $callable) + { + return $this->map(['DELETE'], $pattern, $callable); + } + + /** + * Add OPTIONS route + * + * @param string $pattern The route URI pattern + * @param callable|string $callable The route callback routine + * + * @return \Slim\Interfaces\RouteInterface + */ + public function options($pattern, $callable) + { + return $this->map(['OPTIONS'], $pattern, $callable); + } + + /** + * Add route for any HTTP method + * + * @param string $pattern The route URI pattern + * @param callable|string $callable The route callback routine + * + * @return \Slim\Interfaces\RouteInterface + */ + public function any($pattern, $callable) + { + return $this->map(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], $pattern, $callable); + } + + /** + * Add route with multiple methods + * + * @param string[] $methods Numeric array of HTTP method names + * @param string $pattern The route URI pattern + * @param callable|string $callable The route callback routine + * + * @return RouteInterface + */ + public function map(array $methods, $pattern, $callable) + { + if ($callable instanceof Closure) { + $callable = $callable->bindTo($this->container); + } + + $route = $this->container->get('router')->map($methods, $pattern, $callable); + if (is_callable([$route, 'setContainer'])) { + $route->setContainer($this->container); + } + + if (is_callable([$route, 'setOutputBuffering'])) { + $route->setOutputBuffering($this->container->get('settings')['outputBuffering']); + } + + return $route; + } + + /** + * Route Groups + * + * This method accepts a route pattern and a callback. All route + * declarations in the callback will be prepended by the group(s) + * that it is in. + * + * @param string $pattern + * @param callable $callable + * + * @return RouteGroupInterface + */ + public function group($pattern, $callable) + { + /** @var RouteGroup $group */ + $group = $this->container->get('router')->pushGroup($pattern, $callable); + $group->setContainer($this->container); + $group($this); + $this->container->get('router')->popGroup(); + return $group; + } + + /******************************************************************************** + * Runner + *******************************************************************************/ + + /** + * Run application + * + * This method traverses the application middleware stack and then sends the + * resultant Response object to the HTTP client. + * + * @param bool|false $silent + * @return ResponseInterface + * + * @throws Exception + * @throws MethodNotAllowedException + * @throws NotFoundException + */ + public function run($silent = false) + { + $request = $this->container->get('request'); + $response = $this->container->get('response'); + + $response = $this->process($request, $response); + + if (!$silent) { + $this->respond($response); + } + + return $response; + } + + /** + * Process a request + * + * This method traverses the application middleware stack and then returns the + * resultant Response object. + * + * @param ServerRequestInterface $request + * @param ResponseInterface $response + * @return ResponseInterface + * + * @throws Exception + * @throws MethodNotAllowedException + * @throws NotFoundException + */ + public function process(ServerRequestInterface $request, ResponseInterface $response) + { + // Ensure basePath is set + $router = $this->container->get('router'); + if (is_callable([$request->getUri(), 'getBasePath']) && is_callable([$router, 'setBasePath'])) { + $router->setBasePath($request->getUri()->getBasePath()); + } + + // Dispatch the Router first if the setting for this is on + if ($this->container->get('settings')['determineRouteBeforeAppMiddleware'] === true) { + // Dispatch router (note: you won't be able to alter routes after this) + $request = $this->dispatchRouterAndPrepareRoute($request, $router); + } + + // Traverse middleware stack + try { + $response = $this->callMiddlewareStack($request, $response); + } catch (Exception $e) { + $response = $this->handleException($e, $request, $response); + } catch (Throwable $e) { + $response = $this->handlePhpError($e, $request, $response); + } + + $response = $this->finalize($response); + + return $response; + } + + /** + * Send the response the client + * + * @param ResponseInterface $response + */ + public function respond(ResponseInterface $response) + { + // Send response + if (!headers_sent()) { + // Status + header(sprintf( + 'HTTP/%s %s %s', + $response->getProtocolVersion(), + $response->getStatusCode(), + $response->getReasonPhrase() + )); + + // Headers + foreach ($response->getHeaders() as $name => $values) { + foreach ($values as $value) { + header(sprintf('%s: %s', $name, $value), false); + } + } + } + + // Body + if (!$this->isEmptyResponse($response)) { + $body = $response->getBody(); + if ($body->isSeekable()) { + $body->rewind(); + } + $settings = $this->container->get('settings'); + $chunkSize = $settings['responseChunkSize']; + + $contentLength = $response->getHeaderLine('Content-Length'); + if (!$contentLength) { + $contentLength = $body->getSize(); + } + + + if (isset($contentLength)) { + $amountToRead = $contentLength; + while ($amountToRead > 0 && !$body->eof()) { + $data = $body->read(min($chunkSize, $amountToRead)); + echo $data; + + $amountToRead -= strlen($data); + + if (connection_status() != CONNECTION_NORMAL) { + break; + } + } + } else { + while (!$body->eof()) { + echo $body->read($chunkSize); + if (connection_status() != CONNECTION_NORMAL) { + break; + } + } + } + } + } + + /** + * Invoke application + * + * This method implements the middleware interface. It receives + * Request and Response objects, and it returns a Response object + * after compiling the routes registered in the Router and dispatching + * the Request object to the appropriate Route callback routine. + * + * @param ServerRequestInterface $request The most recent Request object + * @param ResponseInterface $response The most recent Response object + * + * @return ResponseInterface + * @throws MethodNotAllowedException + * @throws NotFoundException + */ + public function __invoke(ServerRequestInterface $request, ResponseInterface $response) + { + // Get the route info + $routeInfo = $request->getAttribute('routeInfo'); + + /** @var \Slim\Interfaces\RouterInterface $router */ + $router = $this->container->get('router'); + + // If router hasn't been dispatched or the URI changed then dispatch + if (null === $routeInfo || ($routeInfo['request'] !== [$request->getMethod(), (string) $request->getUri()])) { + $request = $this->dispatchRouterAndPrepareRoute($request, $router); + $routeInfo = $request->getAttribute('routeInfo'); + } + + if ($routeInfo[0] === Dispatcher::FOUND) { + $route = $router->lookupRoute($routeInfo[1]); + return $route->run($request, $response); + } elseif ($routeInfo[0] === Dispatcher::METHOD_NOT_ALLOWED) { + if (!$this->container->has('notAllowedHandler')) { + throw new MethodNotAllowedException($request, $response, $routeInfo[1]); + } + /** @var callable $notAllowedHandler */ + $notAllowedHandler = $this->container->get('notAllowedHandler'); + return $notAllowedHandler($request, $response, $routeInfo[1]); + } + + if (!$this->container->has('notFoundHandler')) { + throw new NotFoundException($request, $response); + } + /** @var callable $notFoundHandler */ + $notFoundHandler = $this->container->get('notFoundHandler'); + return $notFoundHandler($request, $response); + } + + /** + * Perform a sub-request from within an application route + * + * This method allows you to prepare and initiate a sub-request, run within + * the context of the current request. This WILL NOT issue a remote HTTP + * request. Instead, it will route the provided URL, method, headers, + * cookies, body, and server variables against the set of registered + * application routes. The result response object is returned. + * + * @param string $method The request method (e.g., GET, POST, PUT, etc.) + * @param string $path The request URI path + * @param string $query The request URI query string + * @param array $headers The request headers (key-value array) + * @param array $cookies The request cookies (key-value array) + * @param string $bodyContent The request body + * @param ResponseInterface $response The response object (optional) + * @return ResponseInterface + */ + public function subRequest( + $method, + $path, + $query = '', + array $headers = [], + array $cookies = [], + $bodyContent = '', + ResponseInterface $response = null + ) { + $env = $this->container->get('environment'); + $uri = Uri::createFromEnvironment($env)->withPath($path)->withQuery($query); + $headers = new Headers($headers); + $serverParams = $env->all(); + $body = new Body(fopen('php://temp', 'r+')); + $body->write($bodyContent); + $body->rewind(); + $request = new Request($method, $uri, $headers, $cookies, $serverParams, $body); + + if (!$response) { + $response = $this->container->get('response'); + } + + return $this($request, $response); + } + + /** + * Dispatch the router to find the route. Prepare the route for use. + * + * @param ServerRequestInterface $request + * @param RouterInterface $router + * @return ServerRequestInterface + */ + protected function dispatchRouterAndPrepareRoute(ServerRequestInterface $request, RouterInterface $router) + { + $routeInfo = $router->dispatch($request); + + if ($routeInfo[0] === Dispatcher::FOUND) { + $routeArguments = []; + foreach ($routeInfo[2] as $k => $v) { + $routeArguments[$k] = urldecode($v); + } + + $route = $router->lookupRoute($routeInfo[1]); + $route->prepare($request, $routeArguments); + + // add route to the request's attributes in case a middleware or handler needs access to the route + $request = $request->withAttribute('route', $route); + } + + $routeInfo['request'] = [$request->getMethod(), (string) $request->getUri()]; + + return $request->withAttribute('routeInfo', $routeInfo); + } + + /** + * Finalize response + * + * @param ResponseInterface $response + * @return ResponseInterface + */ + protected function finalize(ResponseInterface $response) + { + // stop PHP sending a Content-Type automatically + ini_set('default_mimetype', ''); + + if ($this->isEmptyResponse($response)) { + return $response->withoutHeader('Content-Type')->withoutHeader('Content-Length'); + } + + // Add Content-Length header if `addContentLengthHeader` setting is set + if (isset($this->container->get('settings')['addContentLengthHeader']) && + $this->container->get('settings')['addContentLengthHeader'] == true) { + if (ob_get_length() > 0) { + throw new \RuntimeException("Unexpected data in output buffer. " . + "Maybe you have characters before an opening getBody()->getSize(); + if ($size !== null && !$response->hasHeader('Content-Length')) { + $response = $response->withHeader('Content-Length', (string) $size); + } + } + + return $response; + } + + /** + * Helper method, which returns true if the provided response must not output a body and false + * if the response could have a body. + * + * @see https://tools.ietf.org/html/rfc7231 + * + * @param ResponseInterface $response + * @return bool + */ + protected function isEmptyResponse(ResponseInterface $response) + { + if (method_exists($response, 'isEmpty')) { + return $response->isEmpty(); + } + + return in_array($response->getStatusCode(), [204, 205, 304]); + } + + /** + * Call relevant handler from the Container if needed. If it doesn't exist, + * then just re-throw. + * + * @param Exception $e + * @param ServerRequestInterface $request + * @param ResponseInterface $response + * + * @return ResponseInterface + * @throws Exception if a handler is needed and not found + */ + protected function handleException(Exception $e, ServerRequestInterface $request, ResponseInterface $response) + { + if ($e instanceof MethodNotAllowedException) { + $handler = 'notAllowedHandler'; + $params = [$e->getRequest(), $e->getResponse(), $e->getAllowedMethods()]; + } elseif ($e instanceof NotFoundException) { + $handler = 'notFoundHandler'; + $params = [$e->getRequest(), $e->getResponse()]; + } elseif ($e instanceof SlimException) { + // This is a Stop exception and contains the response + return $e->getResponse(); + } else { + // Other exception, use $request and $response params + $handler = 'errorHandler'; + $params = [$request, $response, $e]; + } + + if ($this->container->has($handler)) { + $callable = $this->container->get($handler); + // Call the registered handler + return call_user_func_array($callable, $params); + } + + // No handlers found, so just throw the exception + throw $e; + } + + /** + * Call relevant handler from the Container if needed. If it doesn't exist, + * then just re-throw. + * + * @param Throwable $e + * @param ServerRequestInterface $request + * @param ResponseInterface $response + * @return ResponseInterface + * @throws Throwable + */ + protected function handlePhpError(Throwable $e, ServerRequestInterface $request, ResponseInterface $response) + { + $handler = 'phpErrorHandler'; + $params = [$request, $response, $e]; + + if ($this->container->has($handler)) { + $callable = $this->container->get($handler); + // Call the registered handler + return call_user_func_array($callable, $params); + } + + // No handlers found, so just throw the exception + throw $e; + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/CallableResolver.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/CallableResolver.php new file mode 100644 index 000000000000..705a9f207fe0 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/CallableResolver.php @@ -0,0 +1,87 @@ +container = $container; + } + + /** + * Resolve toResolve into a closure that that the router can dispatch. + * + * If toResolve is of the format 'class:method', then try to extract 'class' + * from the container otherwise instantiate it and then dispatch 'method'. + * + * @param mixed $toResolve + * + * @return callable + * + * @throws RuntimeException if the callable does not exist + * @throws RuntimeException if the callable is not resolvable + */ + public function resolve($toResolve) + { + $resolved = $toResolve; + + if (!is_callable($toResolve) && is_string($toResolve)) { + // check for slim callable as "class:method" + $callablePattern = '!^([^\:]+)\:([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)$!'; + if (preg_match($callablePattern, $toResolve, $matches)) { + $class = $matches[1]; + $method = $matches[2]; + + if ($this->container->has($class)) { + $resolved = [$this->container->get($class), $method]; + } else { + if (!class_exists($class)) { + throw new RuntimeException(sprintf('Callable %s does not exist', $class)); + } + $resolved = [new $class($this->container), $method]; + } + } else { + // check if string is something in the DIC that's callable or is a class name which + // has an __invoke() method + $class = $toResolve; + if ($this->container->has($class)) { + $resolved = $this->container->get($class); + } else { + if (!class_exists($class)) { + throw new RuntimeException(sprintf('Callable %s does not exist', $class)); + } + $resolved = new $class($this->container); + } + } + } + + if (!is_callable($resolved)) { + throw new RuntimeException(sprintf('%s is not resolvable', $toResolve)); + } + + return $resolved; + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/CallableResolverAwareTrait.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/CallableResolverAwareTrait.php new file mode 100644 index 000000000000..f7ff485282d2 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/CallableResolverAwareTrait.php @@ -0,0 +1,47 @@ +container instanceof ContainerInterface) { + return $callable; + } + + /** @var CallableResolverInterface $resolver */ + $resolver = $this->container->get('callableResolver'); + + return $resolver->resolve($callable); + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Collection.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Collection.php new file mode 100644 index 000000000000..d33acd9ce32d --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Collection.php @@ -0,0 +1,204 @@ + $value) { + $this->set($key, $value); + } + } + + /******************************************************************************** + * Collection interface + *******************************************************************************/ + + /** + * Set collection item + * + * @param string $key The data key + * @param mixed $value The data value + */ + public function set($key, $value) + { + $this->data[$key] = $value; + } + + /** + * Get collection item for key + * + * @param string $key The data key + * @param mixed $default The default value to return if data key does not exist + * + * @return mixed The key's value, or the default value + */ + public function get($key, $default = null) + { + return $this->has($key) ? $this->data[$key] : $default; + } + + /** + * Add item to collection + * + * @param array $items Key-value array of data to append to this collection + */ + public function replace(array $items) + { + foreach ($items as $key => $value) { + $this->set($key, $value); + } + } + + /** + * Get all items in collection + * + * @return array The collection's source data + */ + public function all() + { + return $this->data; + } + + /** + * Get collection keys + * + * @return array The collection's source data keys + */ + public function keys() + { + return array_keys($this->data); + } + + /** + * Does this collection have a given key? + * + * @param string $key The data key + * + * @return bool + */ + public function has($key) + { + return array_key_exists($key, $this->data); + } + + /** + * Remove item from collection + * + * @param string $key The data key + */ + public function remove($key) + { + unset($this->data[$key]); + } + + /** + * Remove all items from collection + */ + public function clear() + { + $this->data = []; + } + + /******************************************************************************** + * ArrayAccess interface + *******************************************************************************/ + + /** + * Does this collection have a given key? + * + * @param string $key The data key + * + * @return bool + */ + public function offsetExists($key) + { + return $this->has($key); + } + + /** + * Get collection item for key + * + * @param string $key The data key + * + * @return mixed The key's value, or the default value + */ + public function offsetGet($key) + { + return $this->get($key); + } + + /** + * Set collection item + * + * @param string $key The data key + * @param mixed $value The data value + */ + public function offsetSet($key, $value) + { + $this->set($key, $value); + } + + /** + * Remove item from collection + * + * @param string $key The data key + */ + public function offsetUnset($key) + { + $this->remove($key); + } + + /** + * Get number of items in collection + * + * @return int + */ + public function count() + { + return count($this->data); + } + + /******************************************************************************** + * IteratorAggregate interface + *******************************************************************************/ + + /** + * Get collection iterator + * + * @return \ArrayIterator + */ + public function getIterator() + { + return new ArrayIterator($this->data); + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Container.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Container.php new file mode 100644 index 000000000000..c97f2b3fdf44 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Container.php @@ -0,0 +1,181 @@ + '1.1', + 'responseChunkSize' => 4096, + 'outputBuffering' => 'append', + 'determineRouteBeforeAppMiddleware' => false, + 'displayErrorDetails' => false, + 'addContentLengthHeader' => true, + 'routerCacheFile' => false, + ]; + + /** + * Create new container + * + * @param array $values The parameters or objects. + */ + public function __construct(array $values = []) + { + parent::__construct($values); + + $userSettings = isset($values['settings']) ? $values['settings'] : []; + $this->registerDefaultServices($userSettings); + } + + /** + * This function registers the default services that Slim needs to work. + * + * All services are shared - that is, they are registered such that the + * same instance is returned on subsequent calls. + * + * @param array $userSettings Associative array of application settings + * + * @return void + */ + private function registerDefaultServices($userSettings) + { + $defaultSettings = $this->defaultSettings; + + /** + * This service MUST return an array or an + * instance of \ArrayAccess. + * + * @return array|\ArrayAccess + */ + $this['settings'] = function () use ($userSettings, $defaultSettings) { + return new Collection(array_merge($defaultSettings, $userSettings)); + }; + + $defaultProvider = new DefaultServicesProvider(); + $defaultProvider->register($this); + } + + /******************************************************************************** + * Methods to satisfy Interop\Container\ContainerInterface + *******************************************************************************/ + + /** + * Finds an entry of the container by its identifier and returns it. + * + * @param string $id Identifier of the entry to look for. + * + * @throws ContainerValueNotFoundException No entry was found for this identifier. + * @throws ContainerException Error while retrieving the entry. + * + * @return mixed Entry. + */ + public function get($id) + { + if (!$this->offsetExists($id)) { + throw new ContainerValueNotFoundException(sprintf('Identifier "%s" is not defined.', $id)); + } + try { + return $this->offsetGet($id); + } catch (\InvalidArgumentException $exception) { + if ($this->exceptionThrownByContainer($exception)) { + throw new SlimContainerException( + sprintf('Container error while retrieving "%s"', $id), + null, + $exception + ); + } else { + throw $exception; + } + } + } + + /** + * Tests whether an exception needs to be recast for compliance with Container-Interop. This will be if the + * exception was thrown by Pimple. + * + * @param \InvalidArgumentException $exception + * + * @return bool + */ + private function exceptionThrownByContainer(\InvalidArgumentException $exception) + { + $trace = $exception->getTrace()[0]; + + return $trace['class'] === PimpleContainer::class && $trace['function'] === 'offsetGet'; + } + + /** + * Returns true if the container can return an entry for the given identifier. + * Returns false otherwise. + * + * @param string $id Identifier of the entry to look for. + * + * @return boolean + */ + public function has($id) + { + return $this->offsetExists($id); + } + + + /******************************************************************************** + * Magic methods for convenience + *******************************************************************************/ + + public function __get($name) + { + return $this->get($name); + } + + public function __isset($name) + { + return $this->has($name); + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/DefaultServicesProvider.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/DefaultServicesProvider.php new file mode 100644 index 000000000000..c18d8757204d --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/DefaultServicesProvider.php @@ -0,0 +1,204 @@ +get('environment')); + }; + } + + if (!isset($container['response'])) { + /** + * PSR-7 Response object + * + * @param Container $container + * + * @return ResponseInterface + */ + $container['response'] = function ($container) { + $headers = new Headers(['Content-Type' => 'text/html; charset=UTF-8']); + $response = new Response(200, $headers); + + return $response->withProtocolVersion($container->get('settings')['httpVersion']); + }; + } + + if (!isset($container['router'])) { + /** + * This service MUST return a SHARED instance + * of \Slim\Interfaces\RouterInterface. + * + * @param Container $container + * + * @return RouterInterface + */ + $container['router'] = function ($container) { + $routerCacheFile = false; + if (isset($container->get('settings')['routerCacheFile'])) { + $routerCacheFile = $container->get('settings')['routerCacheFile']; + } + + return (new Router)->setCacheFile($routerCacheFile); + }; + } + + if (!isset($container['foundHandler'])) { + /** + * This service MUST return a SHARED instance + * of \Slim\Interfaces\InvocationStrategyInterface. + * + * @return InvocationStrategyInterface + */ + $container['foundHandler'] = function () { + return new RequestResponse; + }; + } + + if (!isset($container['phpErrorHandler'])) { + /** + * This service MUST return a callable + * that accepts three arguments: + * + * 1. Instance of \Psr\Http\Message\ServerRequestInterface + * 2. Instance of \Psr\Http\Message\ResponseInterface + * 3. Instance of \Error + * + * The callable MUST return an instance of + * \Psr\Http\Message\ResponseInterface. + * + * @param Container $container + * + * @return callable + */ + $container['phpErrorHandler'] = function ($container) { + return new PhpError($container->get('settings')['displayErrorDetails']); + }; + } + + if (!isset($container['errorHandler'])) { + /** + * This service MUST return a callable + * that accepts three arguments: + * + * 1. Instance of \Psr\Http\Message\ServerRequestInterface + * 2. Instance of \Psr\Http\Message\ResponseInterface + * 3. Instance of \Exception + * + * The callable MUST return an instance of + * \Psr\Http\Message\ResponseInterface. + * + * @param Container $container + * + * @return callable + */ + $container['errorHandler'] = function ($container) { + return new Error($container->get('settings')['displayErrorDetails']); + }; + } + + if (!isset($container['notFoundHandler'])) { + /** + * This service MUST return a callable + * that accepts two arguments: + * + * 1. Instance of \Psr\Http\Message\ServerRequestInterface + * 2. Instance of \Psr\Http\Message\ResponseInterface + * + * The callable MUST return an instance of + * \Psr\Http\Message\ResponseInterface. + * + * @return callable + */ + $container['notFoundHandler'] = function () { + return new NotFound; + }; + } + + if (!isset($container['notAllowedHandler'])) { + /** + * This service MUST return a callable + * that accepts three arguments: + * + * 1. Instance of \Psr\Http\Message\ServerRequestInterface + * 2. Instance of \Psr\Http\Message\ResponseInterface + * 3. Array of allowed HTTP methods + * + * The callable MUST return an instance of + * \Psr\Http\Message\ResponseInterface. + * + * @return callable + */ + $container['notAllowedHandler'] = function () { + return new NotAllowed; + }; + } + + if (!isset($container['callableResolver'])) { + /** + * Instance of \Slim\Interfaces\CallableResolverInterface + * + * @param Container $container + * + * @return CallableResolverInterface + */ + $container['callableResolver'] = function ($container) { + return new CallableResolver($container); + }; + } + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/DeferredCallable.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/DeferredCallable.php new file mode 100644 index 000000000000..def58ab23b36 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/DeferredCallable.php @@ -0,0 +1,39 @@ +callable = $callable; + $this->container = $container; + } + + public function __invoke() + { + $callable = $this->resolveCallable($this->callable); + if ($callable instanceof Closure) { + $callable = $callable->bindTo($this->container); + } + + $args = func_get_args(); + + return call_user_func_array($callable, $args); + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Exception/ContainerException.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Exception/ContainerException.php new file mode 100644 index 000000000000..0200e1a8611d --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Exception/ContainerException.php @@ -0,0 +1,20 @@ +allowedMethods = $allowedMethods; + } + + /** + * Get allowed methods + * + * @return string[] + */ + public function getAllowedMethods() + { + return $this->allowedMethods; + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Exception/NotFoundException.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Exception/NotFoundException.php new file mode 100644 index 000000000000..65365eb99d6c --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Exception/NotFoundException.php @@ -0,0 +1,14 @@ +request = $request; + $this->response = $response; + } + + /** + * Get request + * + * @return ServerRequestInterface + */ + public function getRequest() + { + return $this->request; + } + + /** + * Get response + * + * @return ResponseInterface + */ + public function getResponse() + { + return $this->response; + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/AbstractError.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/AbstractError.php new file mode 100644 index 000000000000..5a6cee30a941 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/AbstractError.php @@ -0,0 +1,99 @@ +displayErrorDetails = (bool) $displayErrorDetails; + } + + /** + * Write to the error log if displayErrorDetails is false + * + * @param \Exception|\Throwable $throwable + * + * @return void + */ + protected function writeToErrorLog($throwable) + { + if ($this->displayErrorDetails) { + return; + } + + $message = 'Slim Application Error:' . PHP_EOL; + $message .= $this->renderThrowableAsText($throwable); + while ($throwable = $throwable->getPrevious()) { + $message .= PHP_EOL . 'Previous error:' . PHP_EOL; + $message .= $this->renderThrowableAsText($throwable); + } + + $message .= PHP_EOL . 'View in rendered output by enabling the "displayErrorDetails" setting.' . PHP_EOL; + + $this->logError($message); + } + + /** + * Render error as Text. + * + * @param \Exception|\Throwable $throwable + * + * @return string + */ + protected function renderThrowableAsText($throwable) + { + $text = sprintf('Type: %s' . PHP_EOL, get_class($throwable)); + + if ($code = $throwable->getCode()) { + $text .= sprintf('Code: %s' . PHP_EOL, $code); + } + + if ($message = $throwable->getMessage()) { + $text .= sprintf('Message: %s' . PHP_EOL, htmlentities($message)); + } + + if ($file = $throwable->getFile()) { + $text .= sprintf('File: %s' . PHP_EOL, $file); + } + + if ($line = $throwable->getLine()) { + $text .= sprintf('Line: %s' . PHP_EOL, $line); + } + + if ($trace = $throwable->getTraceAsString()) { + $text .= sprintf('Trace: %s', $trace); + } + + return $text; + } + + /** + * Wraps the error_log function so that this can be easily tested + * + * @param $message + */ + protected function logError($message) + { + error_log($message); + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/AbstractHandler.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/AbstractHandler.php new file mode 100644 index 000000000000..decdf725ce89 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/AbstractHandler.php @@ -0,0 +1,59 @@ +getHeaderLine('Accept'); + $selectedContentTypes = array_intersect(explode(',', $acceptHeader), $this->knownContentTypes); + + if (count($selectedContentTypes)) { + return current($selectedContentTypes); + } + + // handle +json and +xml specially + if (preg_match('/\+(json|xml)/', $acceptHeader, $matches)) { + $mediaType = 'application/' . $matches[1]; + if (in_array($mediaType, $this->knownContentTypes)) { + return $mediaType; + } + } + + return 'text/html'; + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/Error.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/Error.php new file mode 100644 index 000000000000..b9951888efb8 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/Error.php @@ -0,0 +1,206 @@ +determineContentType($request); + switch ($contentType) { + case 'application/json': + $output = $this->renderJsonErrorMessage($exception); + break; + + case 'text/xml': + case 'application/xml': + $output = $this->renderXmlErrorMessage($exception); + break; + + case 'text/html': + $output = $this->renderHtmlErrorMessage($exception); + break; + + default: + throw new UnexpectedValueException('Cannot render unknown content type ' . $contentType); + } + + $this->writeToErrorLog($exception); + + $body = new Body(fopen('php://temp', 'r+')); + $body->write($output); + + return $response + ->withStatus(500) + ->withHeader('Content-type', $contentType) + ->withBody($body); + } + + /** + * Render HTML error page + * + * @param \Exception $exception + * + * @return string + */ + protected function renderHtmlErrorMessage(\Exception $exception) + { + $title = 'Slim Application Error'; + + if ($this->displayErrorDetails) { + $html = '

The application could not run because of the following error:

'; + $html .= '

Details

'; + $html .= $this->renderHtmlException($exception); + + while ($exception = $exception->getPrevious()) { + $html .= '

Previous exception

'; + $html .= $this->renderHtmlException($exception); + } + } else { + $html = '

A website error has occurred. Sorry for the temporary inconvenience.

'; + } + + $output = sprintf( + "" . + "%s

%s

%s", + $title, + $title, + $html + ); + + return $output; + } + + /** + * Render exception as HTML. + * + * @param \Exception $exception + * + * @return string + */ + protected function renderHtmlException(\Exception $exception) + { + $html = sprintf('
Type: %s
', get_class($exception)); + + if (($code = $exception->getCode())) { + $html .= sprintf('
Code: %s
', $code); + } + + if (($message = $exception->getMessage())) { + $html .= sprintf('
Message: %s
', htmlentities($message)); + } + + if (($file = $exception->getFile())) { + $html .= sprintf('
File: %s
', $file); + } + + if (($line = $exception->getLine())) { + $html .= sprintf('
Line: %s
', $line); + } + + if (($trace = $exception->getTraceAsString())) { + $html .= '

Trace

'; + $html .= sprintf('
%s
', htmlentities($trace)); + } + + return $html; + } + + /** + * Render JSON error + * + * @param \Exception $exception + * + * @return string + */ + protected function renderJsonErrorMessage(\Exception $exception) + { + $error = [ + 'message' => 'Slim Application Error', + ]; + + if ($this->displayErrorDetails) { + $error['exception'] = []; + + do { + $error['exception'][] = [ + 'type' => get_class($exception), + 'code' => $exception->getCode(), + 'message' => $exception->getMessage(), + 'file' => $exception->getFile(), + 'line' => $exception->getLine(), + 'trace' => explode("\n", $exception->getTraceAsString()), + ]; + } while ($exception = $exception->getPrevious()); + } + + return json_encode($error, JSON_PRETTY_PRINT); + } + + /** + * Render XML error + * + * @param \Exception $exception + * + * @return string + */ + protected function renderXmlErrorMessage(\Exception $exception) + { + $xml = "\n Slim Application Error\n"; + if ($this->displayErrorDetails) { + do { + $xml .= " \n"; + $xml .= " " . get_class($exception) . "\n"; + $xml .= " " . $exception->getCode() . "\n"; + $xml .= " " . $this->createCdataSection($exception->getMessage()) . "\n"; + $xml .= " " . $exception->getFile() . "\n"; + $xml .= " " . $exception->getLine() . "\n"; + $xml .= " " . $this->createCdataSection($exception->getTraceAsString()) . "\n"; + $xml .= " \n"; + } while ($exception = $exception->getPrevious()); + } + $xml .= ""; + + return $xml; + } + + /** + * Returns a CDATA section with the given content. + * + * @param string $content + * @return string + */ + private function createCdataSection($content) + { + return sprintf('', str_replace(']]>', ']]]]>', $content)); + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/NotAllowed.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/NotAllowed.php new file mode 100644 index 000000000000..3442f20bc528 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/NotAllowed.php @@ -0,0 +1,147 @@ +getMethod() === 'OPTIONS') { + $status = 200; + $contentType = 'text/plain'; + $output = $this->renderPlainNotAllowedMessage($methods); + } else { + $status = 405; + $contentType = $this->determineContentType($request); + switch ($contentType) { + case 'application/json': + $output = $this->renderJsonNotAllowedMessage($methods); + break; + + case 'text/xml': + case 'application/xml': + $output = $this->renderXmlNotAllowedMessage($methods); + break; + + case 'text/html': + $output = $this->renderHtmlNotAllowedMessage($methods); + break; + default: + throw new UnexpectedValueException('Cannot render unknown content type ' . $contentType); + } + } + + $body = new Body(fopen('php://temp', 'r+')); + $body->write($output); + $allow = implode(', ', $methods); + + return $response + ->withStatus($status) + ->withHeader('Content-type', $contentType) + ->withHeader('Allow', $allow) + ->withBody($body); + } + + /** + * Render PLAIN not allowed message + * + * @param array $methods + * @return string + */ + protected function renderPlainNotAllowedMessage($methods) + { + $allow = implode(', ', $methods); + + return 'Allowed methods: ' . $allow; + } + + /** + * Render JSON not allowed message + * + * @param array $methods + * @return string + */ + protected function renderJsonNotAllowedMessage($methods) + { + $allow = implode(', ', $methods); + + return '{"message":"Method not allowed. Must be one of: ' . $allow . '"}'; + } + + /** + * Render XML not allowed message + * + * @param array $methods + * @return string + */ + protected function renderXmlNotAllowedMessage($methods) + { + $allow = implode(', ', $methods); + + return "Method not allowed. Must be one of: $allow"; + } + + /** + * Render HTML not allowed message + * + * @param array $methods + * @return string + */ + protected function renderHtmlNotAllowedMessage($methods) + { + $allow = implode(', ', $methods); + $output = << + + Method not allowed + + + +

Method not allowed

+

Method not allowed. Must be one of: $allow

+ + +END; + + return $output; + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/NotFound.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/NotFound.php new file mode 100644 index 000000000000..ab1d47a4575d --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/NotFound.php @@ -0,0 +1,126 @@ +determineContentType($request); + switch ($contentType) { + case 'application/json': + $output = $this->renderJsonNotFoundOutput(); + break; + + case 'text/xml': + case 'application/xml': + $output = $this->renderXmlNotFoundOutput(); + break; + + case 'text/html': + $output = $this->renderHtmlNotFoundOutput($request); + break; + + default: + throw new UnexpectedValueException('Cannot render unknown content type ' . $contentType); + } + + $body = new Body(fopen('php://temp', 'r+')); + $body->write($output); + + return $response->withStatus(404) + ->withHeader('Content-Type', $contentType) + ->withBody($body); + } + + /** + * Return a response for application/json content not found + * + * @return ResponseInterface + */ + protected function renderJsonNotFoundOutput() + { + return '{"message":"Not found"}'; + } + + /** + * Return a response for xml content not found + * + * @return ResponseInterface + */ + protected function renderXmlNotFoundOutput() + { + return 'Not found'; + } + + /** + * Return a response for text/html content not found + * + * @param ServerRequestInterface $request The most recent Request object + * + * @return ResponseInterface + */ + protected function renderHtmlNotFoundOutput(ServerRequestInterface $request) + { + $homeUrl = (string)($request->getUri()->withPath('')->withQuery('')->withFragment('')); + return << + + Page Not Found + + + +

Page Not Found

+

+ The page you are looking for could not be found. Check the address bar + to ensure your URL is spelled correctly. If all else fails, you can + visit our home page at the link below. +

+
Visit the Home Page + + +END; + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/PhpError.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/PhpError.php new file mode 100644 index 000000000000..0122ddb07852 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/PhpError.php @@ -0,0 +1,205 @@ +determineContentType($request); + switch ($contentType) { + case 'application/json': + $output = $this->renderJsonErrorMessage($error); + break; + + case 'text/xml': + case 'application/xml': + $output = $this->renderXmlErrorMessage($error); + break; + + case 'text/html': + $output = $this->renderHtmlErrorMessage($error); + break; + default: + throw new UnexpectedValueException('Cannot render unknown content type ' . $contentType); + } + + $this->writeToErrorLog($error); + + $body = new Body(fopen('php://temp', 'r+')); + $body->write($output); + + return $response + ->withStatus(500) + ->withHeader('Content-type', $contentType) + ->withBody($body); + } + + /** + * Render HTML error page + * + * @param \Throwable $error + * + * @return string + */ + protected function renderHtmlErrorMessage(\Throwable $error) + { + $title = 'Slim Application Error'; + + if ($this->displayErrorDetails) { + $html = '

The application could not run because of the following error:

'; + $html .= '

Details

'; + $html .= $this->renderHtmlError($error); + + while ($error = $error->getPrevious()) { + $html .= '

Previous error

'; + $html .= $this->renderHtmlError($error); + } + } else { + $html = '

A website error has occurred. Sorry for the temporary inconvenience.

'; + } + + $output = sprintf( + "" . + "%s

%s

%s", + $title, + $title, + $html + ); + + return $output; + } + + /** + * Render error as HTML. + * + * @param \Throwable $error + * + * @return string + */ + protected function renderHtmlError(\Throwable $error) + { + $html = sprintf('
Type: %s
', get_class($error)); + + if (($code = $error->getCode())) { + $html .= sprintf('
Code: %s
', $code); + } + + if (($message = $error->getMessage())) { + $html .= sprintf('
Message: %s
', htmlentities($message)); + } + + if (($file = $error->getFile())) { + $html .= sprintf('
File: %s
', $file); + } + + if (($line = $error->getLine())) { + $html .= sprintf('
Line: %s
', $line); + } + + if (($trace = $error->getTraceAsString())) { + $html .= '

Trace

'; + $html .= sprintf('
%s
', htmlentities($trace)); + } + + return $html; + } + + /** + * Render JSON error + * + * @param \Throwable $error + * + * @return string + */ + protected function renderJsonErrorMessage(\Throwable $error) + { + $json = [ + 'message' => 'Slim Application Error', + ]; + + if ($this->displayErrorDetails) { + $json['error'] = []; + + do { + $json['error'][] = [ + 'type' => get_class($error), + 'code' => $error->getCode(), + 'message' => $error->getMessage(), + 'file' => $error->getFile(), + 'line' => $error->getLine(), + 'trace' => explode("\n", $error->getTraceAsString()), + ]; + } while ($error = $error->getPrevious()); + } + + return json_encode($json, JSON_PRETTY_PRINT); + } + + /** + * Render XML error + * + * @param \Throwable $error + * + * @return string + */ + protected function renderXmlErrorMessage(\Throwable $error) + { + $xml = "\n Slim Application Error\n"; + if ($this->displayErrorDetails) { + do { + $xml .= " \n"; + $xml .= " " . get_class($error) . "\n"; + $xml .= " " . $error->getCode() . "\n"; + $xml .= " " . $this->createCdataSection($error->getMessage()) . "\n"; + $xml .= " " . $error->getFile() . "\n"; + $xml .= " " . $error->getLine() . "\n"; + $xml .= " " . $this->createCdataSection($error->getTraceAsString()) . "\n"; + $xml .= " \n"; + } while ($error = $error->getPrevious()); + } + $xml .= ""; + + return $xml; + } + + /** + * Returns a CDATA section with the given content. + * + * @param string $content + * @return string + */ + private function createCdataSection($content) + { + return sprintf('', str_replace(']]>', ']]]]>', $content)); + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php new file mode 100644 index 000000000000..157bdebee947 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php @@ -0,0 +1,43 @@ + $v) { + $request = $request->withAttribute($k, $v); + } + + return call_user_func($callable, $request, $response, $routeArguments); + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php new file mode 100644 index 000000000000..11793d36e403 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php @@ -0,0 +1,42 @@ + '', + 'domain' => null, + 'hostonly' => null, + 'path' => null, + 'expires' => null, + 'secure' => false, + 'httponly' => false + ]; + + /** + * Create new cookies helper + * + * @param array $cookies + */ + public function __construct(array $cookies = []) + { + $this->requestCookies = $cookies; + } + + /** + * Set default cookie properties + * + * @param array $settings + */ + public function setDefaults(array $settings) + { + $this->defaults = array_replace($this->defaults, $settings); + } + + /** + * Get request cookie + * + * @param string $name Cookie name + * @param mixed $default Cookie default value + * + * @return mixed Cookie value if present, else default + */ + public function get($name, $default = null) + { + return isset($this->requestCookies[$name]) ? $this->requestCookies[$name] : $default; + } + + /** + * Set response cookie + * + * @param string $name Cookie name + * @param string|array $value Cookie value, or cookie properties + */ + public function set($name, $value) + { + if (!is_array($value)) { + $value = ['value' => (string)$value]; + } + $this->responseCookies[$name] = array_replace($this->defaults, $value); + } + + /** + * Convert to `Set-Cookie` headers + * + * @return string[] + */ + public function toHeaders() + { + $headers = []; + foreach ($this->responseCookies as $name => $properties) { + $headers[] = $this->toHeader($name, $properties); + } + + return $headers; + } + + /** + * Convert to `Set-Cookie` header + * + * @param string $name Cookie name + * @param array $properties Cookie properties + * + * @return string + */ + protected function toHeader($name, array $properties) + { + $result = urlencode($name) . '=' . urlencode($properties['value']); + + if (isset($properties['domain'])) { + $result .= '; domain=' . $properties['domain']; + } + + if (isset($properties['path'])) { + $result .= '; path=' . $properties['path']; + } + + if (isset($properties['expires'])) { + if (is_string($properties['expires'])) { + $timestamp = strtotime($properties['expires']); + } else { + $timestamp = (int)$properties['expires']; + } + if ($timestamp !== 0) { + $result .= '; expires=' . gmdate('D, d-M-Y H:i:s e', $timestamp); + } + } + + if (isset($properties['secure']) && $properties['secure']) { + $result .= '; secure'; + } + + if (isset($properties['hostonly']) && $properties['hostonly']) { + $result .= '; HostOnly'; + } + + if (isset($properties['httponly']) && $properties['httponly']) { + $result .= '; HttpOnly'; + } + + return $result; + } + + /** + * Parse HTTP request `Cookie:` header and extract + * into a PHP associative array. + * + * @param string $header The raw HTTP request `Cookie:` header + * + * @return array Associative array of cookie names and values + * + * @throws InvalidArgumentException if the cookie data cannot be parsed + */ + public static function parseHeader($header) + { + if (is_array($header) === true) { + $header = isset($header[0]) ? $header[0] : ''; + } + + if (is_string($header) === false) { + throw new InvalidArgumentException('Cannot parse Cookie data. Header value must be a string.'); + } + + $header = rtrim($header, "\r\n"); + $pieces = preg_split('@\s*[;,]\s*@', $header); + $cookies = []; + + foreach ($pieces as $cookie) { + $cookie = explode('=', $cookie, 2); + + if (count($cookie) === 2) { + $key = urldecode($cookie[0]); + $value = urldecode($cookie[1]); + + if (!isset($cookies[$key])) { + $cookies[$key] = $value; + } + } + } + + return $cookies; + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Environment.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Environment.php new file mode 100644 index 000000000000..a106fa8b8770 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Environment.php @@ -0,0 +1,52 @@ + 'HTTP/1.1', + 'REQUEST_METHOD' => 'GET', + 'SCRIPT_NAME' => '', + 'REQUEST_URI' => '', + 'QUERY_STRING' => '', + 'SERVER_NAME' => 'localhost', + 'SERVER_PORT' => 80, + 'HTTP_HOST' => 'localhost', + 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'HTTP_ACCEPT_LANGUAGE' => 'en-US,en;q=0.8', + 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.3', + 'HTTP_USER_AGENT' => 'Slim Framework', + 'REMOTE_ADDR' => '127.0.0.1', + 'REQUEST_TIME' => time(), + 'REQUEST_TIME_FLOAT' => microtime(true), + ], $userData); + + return new static($data); + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Headers.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Headers.php new file mode 100644 index 000000000000..4aa7a5e4de01 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Headers.php @@ -0,0 +1,222 @@ + 1, + 'CONTENT_LENGTH' => 1, + 'PHP_AUTH_USER' => 1, + 'PHP_AUTH_PW' => 1, + 'PHP_AUTH_DIGEST' => 1, + 'AUTH_TYPE' => 1, + ]; + + /** + * Create new headers collection with data extracted from + * the application Environment object + * + * @param Environment $environment The Slim application Environment + * + * @return self + */ + public static function createFromEnvironment(Environment $environment) + { + $data = []; + $environment = self::determineAuthorization($environment); + foreach ($environment as $key => $value) { + $key = strtoupper($key); + if (isset(static::$special[$key]) || strpos($key, 'HTTP_') === 0) { + if ($key !== 'HTTP_CONTENT_LENGTH') { + $data[$key] = $value; + } + } + } + + return new static($data); + } + + /** + * If HTTP_AUTHORIZATION does not exist tries to get it from + * getallheaders() when available. + * + * @param Environment $environment The Slim application Environment + * + * @return Environment + */ + + public static function determineAuthorization(Environment $environment) + { + $authorization = $environment->get('HTTP_AUTHORIZATION'); + + if (null === $authorization && is_callable('getallheaders')) { + $headers = getallheaders(); + $headers = array_change_key_case($headers, CASE_LOWER); + if (isset($headers['authorization'])) { + $environment->set('HTTP_AUTHORIZATION', $headers['authorization']); + } + } + + return $environment; + } + + /** + * Return array of HTTP header names and values. + * This method returns the _original_ header name + * as specified by the end user. + * + * @return array + */ + public function all() + { + $all = parent::all(); + $out = []; + foreach ($all as $key => $props) { + $out[$props['originalKey']] = $props['value']; + } + + return $out; + } + + /** + * Set HTTP header value + * + * This method sets a header value. It replaces + * any values that may already exist for the header name. + * + * @param string $key The case-insensitive header name + * @param string $value The header value + */ + public function set($key, $value) + { + if (!is_array($value)) { + $value = [$value]; + } + parent::set($this->normalizeKey($key), [ + 'value' => $value, + 'originalKey' => $key + ]); + } + + /** + * Get HTTP header value + * + * @param string $key The case-insensitive header name + * @param mixed $default The default value if key does not exist + * + * @return string[] + */ + public function get($key, $default = null) + { + if ($this->has($key)) { + return parent::get($this->normalizeKey($key))['value']; + } + + return $default; + } + + /** + * Get HTTP header key as originally specified + * + * @param string $key The case-insensitive header name + * @param mixed $default The default value if key does not exist + * + * @return string + */ + public function getOriginalKey($key, $default = null) + { + if ($this->has($key)) { + return parent::get($this->normalizeKey($key))['originalKey']; + } + + return $default; + } + + /** + * Add HTTP header value + * + * This method appends a header value. Unlike the set() method, + * this method _appends_ this new value to any values + * that already exist for this header name. + * + * @param string $key The case-insensitive header name + * @param array|string $value The new header value(s) + */ + public function add($key, $value) + { + $oldValues = $this->get($key, []); + $newValues = is_array($value) ? $value : [$value]; + $this->set($key, array_merge($oldValues, array_values($newValues))); + } + + /** + * Does this collection have a given header? + * + * @param string $key The case-insensitive header name + * + * @return bool + */ + public function has($key) + { + return parent::has($this->normalizeKey($key)); + } + + /** + * Remove header from collection + * + * @param string $key The case-insensitive header name + */ + public function remove($key) + { + parent::remove($this->normalizeKey($key)); + } + + /** + * Normalize header name + * + * This method transforms header names into a + * normalized form. This is how we enable case-insensitive + * header names in the other methods in this class. + * + * @param string $key The case-insensitive header name + * + * @return string Normalized header name + */ + public function normalizeKey($key) + { + $key = strtr(strtolower($key), '_', '-'); + if (strpos($key, 'http-') === 0) { + $key = substr($key, 5); + } + + return $key; + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Message.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Message.php new file mode 100644 index 000000000000..d0e832d695f1 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Message.php @@ -0,0 +1,295 @@ +protocolVersion; + } + + /** + * Return an instance with the specified HTTP protocol version. + * + * The version string MUST contain only the HTTP version number (e.g., + * "1.1", "1.0"). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new protocol version. + * + * @param string $version HTTP protocol version + * @return static + * @throws InvalidArgumentException if the http version is an invalid number + */ + public function withProtocolVersion($version) + { + static $valid = [ + '1.0' => true, + '1.1' => true, + '2.0' => true, + ]; + if (!isset($valid[$version])) { + throw new InvalidArgumentException('Invalid HTTP version. Must be one of: 1.0, 1.1, 2.0'); + } + $clone = clone $this; + $clone->protocolVersion = $version; + + return $clone; + } + + /******************************************************************************* + * Headers + ******************************************************************************/ + + /** + * Retrieves all message header values. + * + * The keys represent the header name as it will be sent over the wire, and + * each value is an array of strings associated with the header. + * + * // Represent the headers as a string + * foreach ($message->getHeaders() as $name => $values) { + * echo $name . ": " . implode(", ", $values); + * } + * + * // Emit headers iteratively: + * foreach ($message->getHeaders() as $name => $values) { + * foreach ($values as $value) { + * header(sprintf('%s: %s', $name, $value), false); + * } + * } + * + * While header names are not case-sensitive, getHeaders() will preserve the + * exact case in which headers were originally specified. + * + * @return array Returns an associative array of the message's headers. Each + * key MUST be a header name, and each value MUST be an array of strings + * for that header. + */ + public function getHeaders() + { + return $this->headers->all(); + } + + /** + * Checks if a header exists by the given case-insensitive name. + * + * @param string $name Case-insensitive header field name. + * @return bool Returns true if any header names match the given header + * name using a case-insensitive string comparison. Returns false if + * no matching header name is found in the message. + */ + public function hasHeader($name) + { + return $this->headers->has($name); + } + + /** + * Retrieves a message header value by the given case-insensitive name. + * + * This method returns an array of all the header values of the given + * case-insensitive header name. + * + * If the header does not appear in the message, this method MUST return an + * empty array. + * + * @param string $name Case-insensitive header field name. + * @return string[] An array of string values as provided for the given + * header. If the header does not appear in the message, this method MUST + * return an empty array. + */ + public function getHeader($name) + { + return $this->headers->get($name, []); + } + + /** + * Retrieves a comma-separated string of the values for a single header. + * + * This method returns all of the header values of the given + * case-insensitive header name as a string concatenated together using + * a comma. + * + * NOTE: Not all header values may be appropriately represented using + * comma concatenation. For such headers, use getHeader() instead + * and supply your own delimiter when concatenating. + * + * If the header does not appear in the message, this method MUST return + * an empty string. + * + * @param string $name Case-insensitive header field name. + * @return string A string of values as provided for the given header + * concatenated together using a comma. If the header does not appear in + * the message, this method MUST return an empty string. + */ + public function getHeaderLine($name) + { + return implode(',', $this->headers->get($name, [])); + } + + /** + * Return an instance with the provided value replacing the specified header. + * + * While header names are case-insensitive, the casing of the header will + * be preserved by this function, and returned from getHeaders(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new and/or updated header and value. + * + * @param string $name Case-insensitive header field name. + * @param string|string[] $value Header value(s). + * @return static + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withHeader($name, $value) + { + $clone = clone $this; + $clone->headers->set($name, $value); + + return $clone; + } + + /** + * Return an instance with the specified header appended with the given value. + * + * Existing values for the specified header will be maintained. The new + * value(s) will be appended to the existing list. If the header did not + * exist previously, it will be added. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new header and/or value. + * + * @param string $name Case-insensitive header field name to add. + * @param string|string[] $value Header value(s). + * @return static + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withAddedHeader($name, $value) + { + $clone = clone $this; + $clone->headers->add($name, $value); + + return $clone; + } + + /** + * Return an instance without the specified header. + * + * Header resolution MUST be done without case-sensitivity. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the named header. + * + * @param string $name Case-insensitive header field name to remove. + * @return static + */ + public function withoutHeader($name) + { + $clone = clone $this; + $clone->headers->remove($name); + + return $clone; + } + + /******************************************************************************* + * Body + ******************************************************************************/ + + /** + * Gets the body of the message. + * + * @return StreamInterface Returns the body as a stream. + */ + public function getBody() + { + return $this->body; + } + + /** + * Return an instance with the specified message body. + * + * The body MUST be a StreamInterface object. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return a new instance that has the + * new body stream. + * + * @param StreamInterface $body Body. + * @return static + * @throws \InvalidArgumentException When the body is not valid. + */ + public function withBody(StreamInterface $body) + { + // TODO: Test for invalid body? + $clone = clone $this; + $clone->body = $body; + + return $clone; + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Request.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Request.php new file mode 100644 index 000000000000..7d5b185dcd83 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Request.php @@ -0,0 +1,1156 @@ + 1, + 'DELETE' => 1, + 'GET' => 1, + 'HEAD' => 1, + 'OPTIONS' => 1, + 'PATCH' => 1, + 'POST' => 1, + 'PUT' => 1, + 'TRACE' => 1, + ]; + + /** + * Create new HTTP request with data extracted from the application + * Environment object + * + * @param Environment $environment The Slim application Environment + * + * @return self + */ + public static function createFromEnvironment(Environment $environment) + { + $method = $environment['REQUEST_METHOD']; + $uri = Uri::createFromEnvironment($environment); + $headers = Headers::createFromEnvironment($environment); + $cookies = Cookies::parseHeader($headers->get('Cookie', [])); + $serverParams = $environment->all(); + $body = new RequestBody(); + $uploadedFiles = UploadedFile::createFromEnvironment($environment); + + $request = new static($method, $uri, $headers, $cookies, $serverParams, $body, $uploadedFiles); + + if ($method === 'POST' && + in_array($request->getMediaType(), ['application/x-www-form-urlencoded', 'multipart/form-data']) + ) { + // parsed body must be $_POST + $request = $request->withParsedBody($_POST); + } + return $request; + } + + /** + * Create new HTTP request. + * + * Adds a host header when none was provided and a host is defined in uri. + * + * @param string $method The request method + * @param UriInterface $uri The request URI object + * @param HeadersInterface $headers The request headers collection + * @param array $cookies The request cookies collection + * @param array $serverParams The server environment variables + * @param StreamInterface $body The request body object + * @param array $uploadedFiles The request uploadedFiles collection + */ + public function __construct( + $method, + UriInterface $uri, + HeadersInterface $headers, + array $cookies, + array $serverParams, + StreamInterface $body, + array $uploadedFiles = [] + ) { + $this->originalMethod = $this->filterMethod($method); + $this->uri = $uri; + $this->headers = $headers; + $this->cookies = $cookies; + $this->serverParams = $serverParams; + $this->attributes = new Collection(); + $this->body = $body; + $this->uploadedFiles = $uploadedFiles; + + if (isset($serverParams['SERVER_PROTOCOL'])) { + $this->protocolVersion = str_replace('HTTP/', '', $serverParams['SERVER_PROTOCOL']); + } + + if (!$this->headers->has('Host') || $this->uri->getHost() !== '') { + $this->headers->set('Host', $this->uri->getHost()); + } + + $this->registerMediaTypeParser('application/json', function ($input) { + return json_decode($input, true); + }); + + $this->registerMediaTypeParser('application/xml', function ($input) { + $backup = libxml_disable_entity_loader(true); + $result = simplexml_load_string($input); + libxml_disable_entity_loader($backup); + return $result; + }); + + $this->registerMediaTypeParser('text/xml', function ($input) { + $backup = libxml_disable_entity_loader(true); + $result = simplexml_load_string($input); + libxml_disable_entity_loader($backup); + return $result; + }); + + $this->registerMediaTypeParser('application/x-www-form-urlencoded', function ($input) { + parse_str($input, $data); + return $data; + }); + } + + /** + * This method is applied to the cloned object + * after PHP performs an initial shallow-copy. This + * method completes a deep-copy by creating new objects + * for the cloned object's internal reference pointers. + */ + public function __clone() + { + $this->headers = clone $this->headers; + $this->attributes = clone $this->attributes; + $this->body = clone $this->body; + } + + /******************************************************************************* + * Method + ******************************************************************************/ + + /** + * Retrieves the HTTP method of the request. + * + * @return string Returns the request method. + */ + public function getMethod() + { + if ($this->method === null) { + $this->method = $this->originalMethod; + $customMethod = $this->getHeaderLine('X-Http-Method-Override'); + + if ($customMethod) { + $this->method = $this->filterMethod($customMethod); + } elseif ($this->originalMethod === 'POST') { + $body = $this->getParsedBody(); + + if (is_object($body) && property_exists($body, '_METHOD')) { + $this->method = $this->filterMethod((string)$body->_METHOD); + } elseif (is_array($body) && isset($body['_METHOD'])) { + $this->method = $this->filterMethod((string)$body['_METHOD']); + } + + if ($this->getBody()->eof()) { + $this->getBody()->rewind(); + } + } + } + + return $this->method; + } + + /** + * Get the original HTTP method (ignore override). + * + * Note: This method is not part of the PSR-7 standard. + * + * @return string + */ + public function getOriginalMethod() + { + return $this->originalMethod; + } + + /** + * Return an instance with the provided HTTP method. + * + * While HTTP method names are typically all uppercase characters, HTTP + * method names are case-sensitive and thus implementations SHOULD NOT + * modify the given string. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * changed request method. + * + * @param string $method Case-sensitive method. + * @return self + * @throws \InvalidArgumentException for invalid HTTP methods. + */ + public function withMethod($method) + { + $method = $this->filterMethod($method); + $clone = clone $this; + $clone->originalMethod = $method; + $clone->method = $method; + + return $clone; + } + + /** + * Validate the HTTP method + * + * @param null|string $method + * @return null|string + * @throws \InvalidArgumentException on invalid HTTP method. + */ + protected function filterMethod($method) + { + if ($method === null) { + return $method; + } + + if (!is_string($method)) { + throw new InvalidArgumentException(sprintf( + 'Unsupported HTTP method; must be a string, received %s', + (is_object($method) ? get_class($method) : gettype($method)) + )); + } + + $method = strtoupper($method); + if (!isset($this->validMethods[$method])) { + throw new InvalidArgumentException(sprintf( + 'Unsupported HTTP method "%s" provided', + $method + )); + } + + return $method; + } + + /** + * Does this request use a given method? + * + * Note: This method is not part of the PSR-7 standard. + * + * @param string $method HTTP method + * @return bool + */ + public function isMethod($method) + { + return $this->getMethod() === $method; + } + + /** + * Is this a GET request? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isGet() + { + return $this->isMethod('GET'); + } + + /** + * Is this a POST request? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isPost() + { + return $this->isMethod('POST'); + } + + /** + * Is this a PUT request? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isPut() + { + return $this->isMethod('PUT'); + } + + /** + * Is this a PATCH request? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isPatch() + { + return $this->isMethod('PATCH'); + } + + /** + * Is this a DELETE request? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isDelete() + { + return $this->isMethod('DELETE'); + } + + /** + * Is this a HEAD request? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isHead() + { + return $this->isMethod('HEAD'); + } + + /** + * Is this a OPTIONS request? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isOptions() + { + return $this->isMethod('OPTIONS'); + } + + /** + * Is this an XHR request? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isXhr() + { + return $this->getHeaderLine('X-Requested-With') === 'XMLHttpRequest'; + } + + /******************************************************************************* + * URI + ******************************************************************************/ + + /** + * Retrieves the message's request target. + * + * Retrieves the message's request-target either as it will appear (for + * clients), as it appeared at request (for servers), or as it was + * specified for the instance (see withRequestTarget()). + * + * In most cases, this will be the origin-form of the composed URI, + * unless a value was provided to the concrete implementation (see + * withRequestTarget() below). + * + * If no URI is available, and no request-target has been specifically + * provided, this method MUST return the string "/". + * + * @return string + */ + public function getRequestTarget() + { + if ($this->requestTarget) { + return $this->requestTarget; + } + + if ($this->uri === null) { + return '/'; + } + + $basePath = $this->uri->getBasePath(); + $path = $this->uri->getPath(); + $path = $basePath . '/' . ltrim($path, '/'); + + $query = $this->uri->getQuery(); + if ($query) { + $path .= '?' . $query; + } + $this->requestTarget = $path; + + return $this->requestTarget; + } + + /** + * Return an instance with the specific request-target. + * + * If the request needs a non-origin-form request-target — e.g., for + * specifying an absolute-form, authority-form, or asterisk-form — + * this method may be used to create an instance with the specified + * request-target, verbatim. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * changed request target. + * + * @link http://tools.ietf.org/html/rfc7230#section-2.7 (for the various + * request-target forms allowed in request messages) + * @param mixed $requestTarget + * @return self + * @throws InvalidArgumentException if the request target is invalid + */ + public function withRequestTarget($requestTarget) + { + if (preg_match('#\s#', $requestTarget)) { + throw new InvalidArgumentException( + 'Invalid request target provided; must be a string and cannot contain whitespace' + ); + } + $clone = clone $this; + $clone->requestTarget = $requestTarget; + + return $clone; + } + + /** + * Retrieves the URI instance. + * + * This method MUST return a UriInterface instance. + * + * @link http://tools.ietf.org/html/rfc3986#section-4.3 + * @return UriInterface Returns a UriInterface instance + * representing the URI of the request. + */ + public function getUri() + { + return $this->uri; + } + + /** + * Returns an instance with the provided URI. + * + * This method MUST update the Host header of the returned request by + * default if the URI contains a host component. If the URI does not + * contain a host component, any pre-existing Host header MUST be carried + * over to the returned request. + * + * You can opt-in to preserving the original state of the Host header by + * setting `$preserveHost` to `true`. When `$preserveHost` is set to + * `true`, this method interacts with the Host header in the following ways: + * + * - If the the Host header is missing or empty, and the new URI contains + * a host component, this method MUST update the Host header in the returned + * request. + * - If the Host header is missing or empty, and the new URI does not contain a + * host component, this method MUST NOT update the Host header in the returned + * request. + * - If a Host header is present and non-empty, this method MUST NOT update + * the Host header in the returned request. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new UriInterface instance. + * + * @link http://tools.ietf.org/html/rfc3986#section-4.3 + * @param UriInterface $uri New request URI to use. + * @param bool $preserveHost Preserve the original state of the Host header. + * @return self + */ + public function withUri(UriInterface $uri, $preserveHost = false) + { + $clone = clone $this; + $clone->uri = $uri; + + if (!$preserveHost) { + if ($uri->getHost() !== '') { + $clone->headers->set('Host', $uri->getHost()); + } + } else { + if ($this->uri->getHost() !== '' && (!$this->hasHeader('Host') || $this->getHeader('Host') === null)) { + $clone->headers->set('Host', $uri->getHost()); + } + } + + return $clone; + } + + /** + * Get request content type. + * + * Note: This method is not part of the PSR-7 standard. + * + * @return string|null The request content type, if known + */ + public function getContentType() + { + $result = $this->getHeader('Content-Type'); + + return $result ? $result[0] : null; + } + + /** + * Get request media type, if known. + * + * Note: This method is not part of the PSR-7 standard. + * + * @return string|null The request media type, minus content-type params + */ + public function getMediaType() + { + $contentType = $this->getContentType(); + if ($contentType) { + $contentTypeParts = preg_split('/\s*[;,]\s*/', $contentType); + + return strtolower($contentTypeParts[0]); + } + + return null; + } + + /** + * Get request media type params, if known. + * + * Note: This method is not part of the PSR-7 standard. + * + * @return array + */ + public function getMediaTypeParams() + { + $contentType = $this->getContentType(); + $contentTypeParams = []; + if ($contentType) { + $contentTypeParts = preg_split('/\s*[;,]\s*/', $contentType); + $contentTypePartsLength = count($contentTypeParts); + for ($i = 1; $i < $contentTypePartsLength; $i++) { + $paramParts = explode('=', $contentTypeParts[$i]); + $contentTypeParams[strtolower($paramParts[0])] = $paramParts[1]; + } + } + + return $contentTypeParams; + } + + /** + * Get request content character set, if known. + * + * Note: This method is not part of the PSR-7 standard. + * + * @return string|null + */ + public function getContentCharset() + { + $mediaTypeParams = $this->getMediaTypeParams(); + if (isset($mediaTypeParams['charset'])) { + return $mediaTypeParams['charset']; + } + + return null; + } + + /** + * Get request content length, if known. + * + * Note: This method is not part of the PSR-7 standard. + * + * @return int|null + */ + public function getContentLength() + { + $result = $this->headers->get('Content-Length'); + + return $result ? (int)$result[0] : null; + } + + /******************************************************************************* + * Cookies + ******************************************************************************/ + + /** + * Retrieve cookies. + * + * Retrieves cookies sent by the client to the server. + * + * The data MUST be compatible with the structure of the $_COOKIE + * superglobal. + * + * @return array + */ + public function getCookieParams() + { + return $this->cookies; + } + + /** + * Return an instance with the specified cookies. + * + * The data IS NOT REQUIRED to come from the $_COOKIE superglobal, but MUST + * be compatible with the structure of $_COOKIE. Typically, this data will + * be injected at instantiation. + * + * This method MUST NOT update the related Cookie header of the request + * instance, nor related values in the server params. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated cookie values. + * + * @param array $cookies Array of key/value pairs representing cookies. + * @return self + */ + public function withCookieParams(array $cookies) + { + $clone = clone $this; + $clone->cookies = $cookies; + + return $clone; + } + + /******************************************************************************* + * Query Params + ******************************************************************************/ + + /** + * Retrieve query string arguments. + * + * Retrieves the deserialized query string arguments, if any. + * + * Note: the query params might not be in sync with the URI or server + * params. If you need to ensure you are only getting the original + * values, you may need to parse the query string from `getUri()->getQuery()` + * or from the `QUERY_STRING` server param. + * + * @return array + */ + public function getQueryParams() + { + if (is_array($this->queryParams)) { + return $this->queryParams; + } + + if ($this->uri === null) { + return []; + } + + parse_str($this->uri->getQuery(), $this->queryParams); // <-- URL decodes data + + return $this->queryParams; + } + + /** + * Return an instance with the specified query string arguments. + * + * These values SHOULD remain immutable over the course of the incoming + * request. They MAY be injected during instantiation, such as from PHP's + * $_GET superglobal, or MAY be derived from some other value such as the + * URI. In cases where the arguments are parsed from the URI, the data + * MUST be compatible with what PHP's parse_str() would return for + * purposes of how duplicate query parameters are handled, and how nested + * sets are handled. + * + * Setting query string arguments MUST NOT change the URI stored by the + * request, nor the values in the server params. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated query string arguments. + * + * @param array $query Array of query string arguments, typically from + * $_GET. + * @return self + */ + public function withQueryParams(array $query) + { + $clone = clone $this; + $clone->queryParams = $query; + + return $clone; + } + + /******************************************************************************* + * File Params + ******************************************************************************/ + + /** + * Retrieve normalized file upload data. + * + * This method returns upload metadata in a normalized tree, with each leaf + * an instance of Psr\Http\Message\UploadedFileInterface. + * + * These values MAY be prepared from $_FILES or the message body during + * instantiation, or MAY be injected via withUploadedFiles(). + * + * @return array An array tree of UploadedFileInterface instances; an empty + * array MUST be returned if no data is present. + */ + public function getUploadedFiles() + { + return $this->uploadedFiles; + } + + /** + * Create a new instance with the specified uploaded files. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param array $uploadedFiles An array tree of UploadedFileInterface instances. + * @return self + * @throws \InvalidArgumentException if an invalid structure is provided. + */ + public function withUploadedFiles(array $uploadedFiles) + { + $clone = clone $this; + $clone->uploadedFiles = $uploadedFiles; + + return $clone; + } + + /******************************************************************************* + * Server Params + ******************************************************************************/ + + /** + * Retrieve server parameters. + * + * Retrieves data related to the incoming request environment, + * typically derived from PHP's $_SERVER superglobal. The data IS NOT + * REQUIRED to originate from $_SERVER. + * + * @return array + */ + public function getServerParams() + { + return $this->serverParams; + } + + /******************************************************************************* + * Attributes + ******************************************************************************/ + + /** + * Retrieve attributes derived from the request. + * + * The request "attributes" may be used to allow injection of any + * parameters derived from the request: e.g., the results of path + * match operations; the results of decrypting cookies; the results of + * deserializing non-form-encoded message bodies; etc. Attributes + * will be application and request specific, and CAN be mutable. + * + * @return array Attributes derived from the request. + */ + public function getAttributes() + { + return $this->attributes->all(); + } + + /** + * Retrieve a single derived request attribute. + * + * Retrieves a single derived request attribute as described in + * getAttributes(). If the attribute has not been previously set, returns + * the default value as provided. + * + * This method obviates the need for a hasAttribute() method, as it allows + * specifying a default value to return if the attribute is not found. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $default Default value to return if the attribute does not exist. + * @return mixed + */ + public function getAttribute($name, $default = null) + { + return $this->attributes->get($name, $default); + } + + /** + * Return an instance with the specified derived request attribute. + * + * This method allows setting a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $value The value of the attribute. + * @return self + */ + public function withAttribute($name, $value) + { + $clone = clone $this; + $clone->attributes->set($name, $value); + + return $clone; + } + + /** + * Create a new instance with the specified derived request attributes. + * + * Note: This method is not part of the PSR-7 standard. + * + * This method allows setting all new derived request attributes as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return a new instance that has the + * updated attributes. + * + * @param array $attributes New attributes + * @return self + */ + public function withAttributes(array $attributes) + { + $clone = clone $this; + $clone->attributes = new Collection($attributes); + + return $clone; + } + + /** + * Return an instance that removes the specified derived request attribute. + * + * This method allows removing a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @return self + */ + public function withoutAttribute($name) + { + $clone = clone $this; + $clone->attributes->remove($name); + + return $clone; + } + + /******************************************************************************* + * Body + ******************************************************************************/ + + /** + * Retrieve any parameters provided in the request body. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, this method MUST + * return the contents of $_POST. + * + * Otherwise, this method may return any results of deserializing + * the request body content; as parsing returns structured content, the + * potential types MUST be arrays or objects only. A null value indicates + * the absence of body content. + * + * @return null|array|object The deserialized body parameters, if any. + * These will typically be an array or object. + * @throws RuntimeException if the request body media type parser returns an invalid value + */ + public function getParsedBody() + { + if ($this->bodyParsed !== false) { + return $this->bodyParsed; + } + + if (!$this->body) { + return null; + } + + $mediaType = $this->getMediaType(); + + // look for a media type with a structured syntax suffix (RFC 6839) + $parts = explode('+', $mediaType); + if (count($parts) >= 2) { + $mediaType = 'application/' . $parts[count($parts)-1]; + } + + if (isset($this->bodyParsers[$mediaType]) === true) { + $body = (string)$this->getBody(); + $parsed = $this->bodyParsers[$mediaType]($body); + + if (!is_null($parsed) && !is_object($parsed) && !is_array($parsed)) { + throw new RuntimeException( + 'Request body media type parser return value must be an array, an object, or null' + ); + } + $this->bodyParsed = $parsed; + return $this->bodyParsed; + } + + return null; + } + + /** + * Return an instance with the specified body parameters. + * + * These MAY be injected during instantiation. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, use this method + * ONLY to inject the contents of $_POST. + * + * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of + * deserializing the request body content. Deserialization/parsing returns + * structured data, and, as such, this method ONLY accepts arrays or objects, + * or a null value if nothing was available to parse. + * + * As an example, if content negotiation determines that the request data + * is a JSON payload, this method could be used to create a request + * instance with the deserialized parameters. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param null|array|object $data The deserialized body data. This will + * typically be in an array or object. + * @return self + * @throws \InvalidArgumentException if an unsupported argument type is + * provided. + */ + public function withParsedBody($data) + { + if (!is_null($data) && !is_object($data) && !is_array($data)) { + throw new InvalidArgumentException('Parsed body value must be an array, an object, or null'); + } + + $clone = clone $this; + $clone->bodyParsed = $data; + + return $clone; + } + + /** + * Force Body to be parsed again. + * + * Note: This method is not part of the PSR-7 standard. + * + * @return self + */ + public function reparseBody() + { + $this->bodyParsed = false; + + return $this; + } + + /** + * Register media type parser. + * + * Note: This method is not part of the PSR-7 standard. + * + * @param string $mediaType A HTTP media type (excluding content-type + * params). + * @param callable $callable A callable that returns parsed contents for + * media type. + */ + public function registerMediaTypeParser($mediaType, callable $callable) + { + if ($callable instanceof Closure) { + $callable = $callable->bindTo($this); + } + $this->bodyParsers[(string)$mediaType] = $callable; + } + + /******************************************************************************* + * Parameters (e.g., POST and GET data) + ******************************************************************************/ + + /** + * Fetch request parameter value from body or query string (in that order). + * + * Note: This method is not part of the PSR-7 standard. + * + * @param string $key The parameter key. + * @param string $default The default value. + * + * @return mixed The parameter value. + */ + public function getParam($key, $default = null) + { + $postParams = $this->getParsedBody(); + $getParams = $this->getQueryParams(); + $result = $default; + if (is_array($postParams) && isset($postParams[$key])) { + $result = $postParams[$key]; + } elseif (is_object($postParams) && property_exists($postParams, $key)) { + $result = $postParams->$key; + } elseif (isset($getParams[$key])) { + $result = $getParams[$key]; + } + + return $result; + } + + /** + * Fetch parameter value from request body. + * + * Note: This method is not part of the PSR-7 standard. + * + * @param $key + * @param null $default + * + * @return null + */ + public function getParsedBodyParam($key, $default = null) + { + $postParams = $this->getParsedBody(); + $result = $default; + if (is_array($postParams) && isset($postParams[$key])) { + $result = $postParams[$key]; + } elseif (is_object($postParams) && property_exists($postParams, $key)) { + $result = $postParams->$key; + } + + return $result; + } + + /** + * Fetch parameter value from query string. + * + * Note: This method is not part of the PSR-7 standard. + * + * @param $key + * @param null $default + * + * @return null + */ + public function getQueryParam($key, $default = null) + { + $getParams = $this->getQueryParams(); + $result = $default; + if (isset($getParams[$key])) { + $result = $getParams[$key]; + } + + return $result; + } + + /** + * Fetch assocative array of body and query string parameters. + * + * Note: This method is not part of the PSR-7 standard. + * + * @return array + */ + public function getParams() + { + $params = $this->getQueryParams(); + $postParams = $this->getParsedBody(); + if ($postParams) { + $params = array_merge($params, (array)$postParams); + } + + return $params; + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/RequestBody.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/RequestBody.php new file mode 100644 index 000000000000..2345fe4354c7 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/RequestBody.php @@ -0,0 +1,27 @@ + 'Continue', + 101 => 'Switching Protocols', + 102 => 'Processing', + //Successful 2xx + 200 => 'OK', + 201 => 'Created', + 202 => 'Accepted', + 203 => 'Non-Authoritative Information', + 204 => 'No Content', + 205 => 'Reset Content', + 206 => 'Partial Content', + 207 => 'Multi-Status', + 208 => 'Already Reported', + 226 => 'IM Used', + //Redirection 3xx + 300 => 'Multiple Choices', + 301 => 'Moved Permanently', + 302 => 'Found', + 303 => 'See Other', + 304 => 'Not Modified', + 305 => 'Use Proxy', + 306 => '(Unused)', + 307 => 'Temporary Redirect', + 308 => 'Permanent Redirect', + //Client Error 4xx + 400 => 'Bad Request', + 401 => 'Unauthorized', + 402 => 'Payment Required', + 403 => 'Forbidden', + 404 => 'Not Found', + 405 => 'Method Not Allowed', + 406 => 'Not Acceptable', + 407 => 'Proxy Authentication Required', + 408 => 'Request Timeout', + 409 => 'Conflict', + 410 => 'Gone', + 411 => 'Length Required', + 412 => 'Precondition Failed', + 413 => 'Request Entity Too Large', + 414 => 'Request-URI Too Long', + 415 => 'Unsupported Media Type', + 416 => 'Requested Range Not Satisfiable', + 417 => 'Expectation Failed', + 418 => 'I\'m a teapot', + 422 => 'Unprocessable Entity', + 423 => 'Locked', + 424 => 'Failed Dependency', + 426 => 'Upgrade Required', + 428 => 'Precondition Required', + 429 => 'Too Many Requests', + 431 => 'Request Header Fields Too Large', + 451 => 'Unavailable For Legal Reasons', + //Server Error 5xx + 500 => 'Internal Server Error', + 501 => 'Not Implemented', + 502 => 'Bad Gateway', + 503 => 'Service Unavailable', + 504 => 'Gateway Timeout', + 505 => 'HTTP Version Not Supported', + 506 => 'Variant Also Negotiates', + 507 => 'Insufficient Storage', + 508 => 'Loop Detected', + 510 => 'Not Extended', + 511 => 'Network Authentication Required', + ]; + + /** + * Create new HTTP response. + * + * @param int $status The response status code. + * @param HeadersInterface|null $headers The response headers. + * @param StreamInterface|null $body The response body. + */ + public function __construct($status = 200, HeadersInterface $headers = null, StreamInterface $body = null) + { + $this->status = $this->filterStatus($status); + $this->headers = $headers ? $headers : new Headers(); + $this->body = $body ? $body : new Body(fopen('php://temp', 'r+')); + } + + /** + * This method is applied to the cloned object + * after PHP performs an initial shallow-copy. This + * method completes a deep-copy by creating new objects + * for the cloned object's internal reference pointers. + */ + public function __clone() + { + $this->headers = clone $this->headers; + } + + /******************************************************************************* + * Status + ******************************************************************************/ + + /** + * Gets the response status code. + * + * The status code is a 3-digit integer result code of the server's attempt + * to understand and satisfy the request. + * + * @return int Status code. + */ + public function getStatusCode() + { + return $this->status; + } + + /** + * Return an instance with the specified status code and, optionally, reason phrase. + * + * If no reason phrase is specified, implementations MAY choose to default + * to the RFC 7231 or IANA recommended reason phrase for the response's + * status code. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated status and reason phrase. + * + * @link http://tools.ietf.org/html/rfc7231#section-6 + * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml + * @param int $code The 3-digit integer result code to set. + * @param string $reasonPhrase The reason phrase to use with the + * provided status code; if none is provided, implementations MAY + * use the defaults as suggested in the HTTP specification. + * @return self + * @throws \InvalidArgumentException For invalid status code arguments. + */ + public function withStatus($code, $reasonPhrase = '') + { + $code = $this->filterStatus($code); + + if (!is_string($reasonPhrase) && !method_exists($reasonPhrase, '__toString')) { + throw new InvalidArgumentException('ReasonPhrase must be a string'); + } + + $clone = clone $this; + $clone->status = $code; + if ($reasonPhrase === '' && isset(static::$messages[$code])) { + $reasonPhrase = static::$messages[$code]; + } + + if ($reasonPhrase === '') { + throw new InvalidArgumentException('ReasonPhrase must be supplied for this code'); + } + + $clone->reasonPhrase = $reasonPhrase; + + return $clone; + } + + /** + * Filter HTTP status code. + * + * @param int $status HTTP status code. + * @return int + * @throws \InvalidArgumentException If an invalid HTTP status code is provided. + */ + protected function filterStatus($status) + { + if (!is_integer($status) || $status<100 || $status>599) { + throw new InvalidArgumentException('Invalid HTTP status code'); + } + + return $status; + } + + /** + * Gets the response reason phrase associated with the status code. + * + * Because a reason phrase is not a required element in a response + * status line, the reason phrase value MAY be null. Implementations MAY + * choose to return the default RFC 7231 recommended reason phrase (or those + * listed in the IANA HTTP Status Code Registry) for the response's + * status code. + * + * @link http://tools.ietf.org/html/rfc7231#section-6 + * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml + * @return string Reason phrase; must return an empty string if none present. + */ + public function getReasonPhrase() + { + if ($this->reasonPhrase) { + return $this->reasonPhrase; + } + if (isset(static::$messages[$this->status])) { + return static::$messages[$this->status]; + } + return ''; + } + + /******************************************************************************* + * Body + ******************************************************************************/ + + /** + * Write data to the response body. + * + * Note: This method is not part of the PSR-7 standard. + * + * Proxies to the underlying stream and writes the provided data to it. + * + * @param string $data + * @return self + */ + public function write($data) + { + $this->getBody()->write($data); + + return $this; + } + + /******************************************************************************* + * Response Helpers + ******************************************************************************/ + + /** + * Redirect. + * + * Note: This method is not part of the PSR-7 standard. + * + * This method prepares the response object to return an HTTP Redirect + * response to the client. + * + * @param string|UriInterface $url The redirect destination. + * @param int|null $status The redirect HTTP status code. + * @return self + */ + public function withRedirect($url, $status = null) + { + $responseWithRedirect = $this->withHeader('Location', (string)$url); + + if (is_null($status) && $this->getStatusCode() === 200) { + $status = 302; + } + + if (!is_null($status)) { + return $responseWithRedirect->withStatus($status); + } + + return $responseWithRedirect; + } + + /** + * Json. + * + * Note: This method is not part of the PSR-7 standard. + * + * This method prepares the response object to return an HTTP Json + * response to the client. + * + * @param mixed $data The data + * @param int $status The HTTP status code. + * @param int $encodingOptions Json encoding options + * @throws \RuntimeException + * @return self + */ + public function withJson($data, $status = null, $encodingOptions = 0) + { + $body = $this->getBody(); + $body->rewind(); + $body->write($json = json_encode($data, $encodingOptions)); + + // Ensure that the json encoding passed successfully + if ($json === false) { + throw new \RuntimeException(json_last_error_msg(), json_last_error()); + } + + $responseWithJson = $this->withHeader('Content-Type', 'application/json;charset=utf-8'); + if (isset($status)) { + return $responseWithJson->withStatus($status); + } + return $responseWithJson; + } + + /** + * Is this response empty? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isEmpty() + { + return in_array($this->getStatusCode(), [204, 205, 304]); + } + + /** + * Is this response informational? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isInformational() + { + return $this->getStatusCode() >= 100 && $this->getStatusCode() < 200; + } + + /** + * Is this response OK? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isOk() + { + return $this->getStatusCode() === 200; + } + + /** + * Is this response successful? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isSuccessful() + { + return $this->getStatusCode() >= 200 && $this->getStatusCode() < 300; + } + + /** + * Is this response a redirect? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isRedirect() + { + return in_array($this->getStatusCode(), [301, 302, 303, 307]); + } + + /** + * Is this response a redirection? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isRedirection() + { + return $this->getStatusCode() >= 300 && $this->getStatusCode() < 400; + } + + /** + * Is this response forbidden? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + * @api + */ + public function isForbidden() + { + return $this->getStatusCode() === 403; + } + + /** + * Is this response not Found? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isNotFound() + { + return $this->getStatusCode() === 404; + } + + /** + * Is this response a client error? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isClientError() + { + return $this->getStatusCode() >= 400 && $this->getStatusCode() < 500; + } + + /** + * Is this response a server error? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + public function isServerError() + { + return $this->getStatusCode() >= 500 && $this->getStatusCode() < 600; + } + + /** + * Convert response to string. + * + * Note: This method is not part of the PSR-7 standard. + * + * @return string + */ + public function __toString() + { + $output = sprintf( + 'HTTP/%s %s %s', + $this->getProtocolVersion(), + $this->getStatusCode(), + $this->getReasonPhrase() + ); + $output .= PHP_EOL; + foreach ($this->getHeaders() as $name => $values) { + $output .= sprintf('%s: %s', $name, $this->getHeaderLine($name)) . PHP_EOL; + } + $output .= PHP_EOL; + $output .= (string)$this->getBody(); + + return $output; + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Stream.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Stream.php new file mode 100644 index 000000000000..97de9ac0090a --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Stream.php @@ -0,0 +1,409 @@ + ['r', 'r+', 'w+', 'a+', 'x+', 'c+'], + 'writable' => ['r+', 'w', 'w+', 'a', 'a+', 'x', 'x+', 'c', 'c+'], + ]; + + /** + * The underlying stream resource + * + * @var resource + */ + protected $stream; + + /** + * Stream metadata + * + * @var array + */ + protected $meta; + + /** + * Is this stream readable? + * + * @var bool + */ + protected $readable; + + /** + * Is this stream writable? + * + * @var bool + */ + protected $writable; + + /** + * Is this stream seekable? + * + * @var bool + */ + protected $seekable; + + /** + * The size of the stream if known + * + * @var null|int + */ + protected $size; + + /** + * Create a new Stream. + * + * @param resource $stream A PHP resource handle. + * + * @throws InvalidArgumentException If argument is not a resource. + */ + public function __construct($stream) + { + $this->attach($stream); + } + + /** + * Get stream metadata as an associative array or retrieve a specific key. + * + * The keys returned are identical to the keys returned from PHP's + * stream_get_meta_data() function. + * + * @link http://php.net/manual/en/function.stream-get-meta-data.php + * + * @param string $key Specific metadata to retrieve. + * + * @return array|mixed|null Returns an associative array if no key is + * provided. Returns a specific key value if a key is provided and the + * value is found, or null if the key is not found. + */ + public function getMetadata($key = null) + { + $this->meta = stream_get_meta_data($this->stream); + if (is_null($key) === true) { + return $this->meta; + } + + return isset($this->meta[$key]) ? $this->meta[$key] : null; + } + + /** + * Is a resource attached to this stream? + * + * Note: This method is not part of the PSR-7 standard. + * + * @return bool + */ + protected function isAttached() + { + return is_resource($this->stream); + } + + /** + * Attach new resource to this object. + * + * Note: This method is not part of the PSR-7 standard. + * + * @param resource $newStream A PHP resource handle. + * + * @throws InvalidArgumentException If argument is not a valid PHP resource. + */ + protected function attach($newStream) + { + if (is_resource($newStream) === false) { + throw new InvalidArgumentException(__METHOD__ . ' argument must be a valid PHP resource'); + } + + if ($this->isAttached() === true) { + $this->detach(); + } + + $this->stream = $newStream; + } + + /** + * Separates any underlying resources from the stream. + * + * After the stream has been detached, the stream is in an unusable state. + * + * @return resource|null Underlying PHP stream, if any + */ + public function detach() + { + $oldResource = $this->stream; + $this->stream = null; + $this->meta = null; + $this->readable = null; + $this->writable = null; + $this->seekable = null; + $this->size = null; + + return $oldResource; + } + + /** + * Reads all data from the stream into a string, from the beginning to end. + * + * This method MUST attempt to seek to the beginning of the stream before + * reading data and read the stream until the end is reached. + * + * Warning: This could attempt to load a large amount of data into memory. + * + * This method MUST NOT raise an exception in order to conform with PHP's + * string casting operations. + * + * @see http://php.net/manual/en/language.oop5.magic.php#object.tostring + * @return string + */ + public function __toString() + { + if (!$this->isAttached()) { + return ''; + } + + try { + $this->rewind(); + return $this->getContents(); + } catch (RuntimeException $e) { + return ''; + } + } + + /** + * Closes the stream and any underlying resources. + */ + public function close() + { + if ($this->isAttached() === true) { + fclose($this->stream); + } + + $this->detach(); + } + + /** + * Get the size of the stream if known. + * + * @return int|null Returns the size in bytes if known, or null if unknown. + */ + public function getSize() + { + if (!$this->size && $this->isAttached() === true) { + $stats = fstat($this->stream); + $this->size = isset($stats['size']) ? $stats['size'] : null; + } + + return $this->size; + } + + /** + * Returns the current position of the file read/write pointer + * + * @return int Position of the file pointer + * + * @throws RuntimeException on error. + */ + public function tell() + { + if (!$this->isAttached() || ($position = ftell($this->stream)) === false) { + throw new RuntimeException('Could not get the position of the pointer in stream'); + } + + return $position; + } + + /** + * Returns true if the stream is at the end of the stream. + * + * @return bool + */ + public function eof() + { + return $this->isAttached() ? feof($this->stream) : true; + } + + /** + * Returns whether or not the stream is readable. + * + * @return bool + */ + public function isReadable() + { + if ($this->readable === null) { + $this->readable = false; + if ($this->isAttached()) { + $meta = $this->getMetadata(); + foreach (self::$modes['readable'] as $mode) { + if (strpos($meta['mode'], $mode) === 0) { + $this->readable = true; + break; + } + } + } + } + + return $this->readable; + } + + /** + * Returns whether or not the stream is writable. + * + * @return bool + */ + public function isWritable() + { + if ($this->writable === null) { + $this->writable = false; + if ($this->isAttached()) { + $meta = $this->getMetadata(); + foreach (self::$modes['writable'] as $mode) { + if (strpos($meta['mode'], $mode) === 0) { + $this->writable = true; + break; + } + } + } + } + + return $this->writable; + } + + /** + * Returns whether or not the stream is seekable. + * + * @return bool + */ + public function isSeekable() + { + if ($this->seekable === null) { + $this->seekable = false; + if ($this->isAttached()) { + $meta = $this->getMetadata(); + $this->seekable = $meta['seekable']; + } + } + + return $this->seekable; + } + + /** + * Seek to a position in the stream. + * + * @link http://www.php.net/manual/en/function.fseek.php + * + * @param int $offset Stream offset + * @param int $whence Specifies how the cursor position will be calculated + * based on the seek offset. Valid values are identical to the built-in + * PHP $whence values for `fseek()`. SEEK_SET: Set position equal to + * offset bytes SEEK_CUR: Set position to current location plus offset + * SEEK_END: Set position to end-of-stream plus offset. + * + * @throws RuntimeException on failure. + */ + public function seek($offset, $whence = SEEK_SET) + { + // Note that fseek returns 0 on success! + if (!$this->isSeekable() || fseek($this->stream, $offset, $whence) === -1) { + throw new RuntimeException('Could not seek in stream'); + } + } + + /** + * Seek to the beginning of the stream. + * + * If the stream is not seekable, this method will raise an exception; + * otherwise, it will perform a seek(0). + * + * @see seek() + * + * @link http://www.php.net/manual/en/function.fseek.php + * + * @throws RuntimeException on failure. + */ + public function rewind() + { + if (!$this->isSeekable() || rewind($this->stream) === false) { + throw new RuntimeException('Could not rewind stream'); + } + } + + /** + * Read data from the stream. + * + * @param int $length Read up to $length bytes from the object and return + * them. Fewer than $length bytes may be returned if underlying stream + * call returns fewer bytes. + * + * @return string Returns the data read from the stream, or an empty string + * if no bytes are available. + * + * @throws RuntimeException if an error occurs. + */ + public function read($length) + { + if (!$this->isReadable() || ($data = fread($this->stream, $length)) === false) { + throw new RuntimeException('Could not read from stream'); + } + + return $data; + } + + /** + * Write data to the stream. + * + * @param string $string The string that is to be written. + * + * @return int Returns the number of bytes written to the stream. + * + * @throws RuntimeException on failure. + */ + public function write($string) + { + if (!$this->isWritable() || ($written = fwrite($this->stream, $string)) === false) { + throw new RuntimeException('Could not write to stream'); + } + + // reset size so that it will be recalculated on next call to getSize() + $this->size = null; + + return $written; + } + + /** + * Returns the remaining contents in a string + * + * @return string + * + * @throws RuntimeException if unable to read or an error occurs while + * reading. + */ + public function getContents() + { + if (!$this->isReadable() || ($contents = stream_get_contents($this->stream)) === false) { + throw new RuntimeException('Could not get contents of stream'); + } + + return $contents; + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/UploadedFile.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/UploadedFile.php new file mode 100644 index 000000000000..ff970277c7c7 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/UploadedFile.php @@ -0,0 +1,327 @@ +has('slim.files')) { + return $env['slim.files']; + } elseif (isset($_FILES)) { + return static::parseUploadedFiles($_FILES); + } + + return []; + } + + /** + * Parse a non-normalized, i.e. $_FILES superglobal, tree of uploaded file data. + * + * @param array $uploadedFiles The non-normalized tree of uploaded file data. + * + * @return array A normalized tree of UploadedFile instances. + */ + private static function parseUploadedFiles(array $uploadedFiles) + { + $parsed = []; + foreach ($uploadedFiles as $field => $uploadedFile) { + if (!isset($uploadedFile['error'])) { + if (is_array($uploadedFile)) { + $parsed[$field] = static::parseUploadedFiles($uploadedFile); + } + continue; + } + + $parsed[$field] = []; + if (!is_array($uploadedFile['error'])) { + $parsed[$field] = new static( + $uploadedFile['tmp_name'], + isset($uploadedFile['name']) ? $uploadedFile['name'] : null, + isset($uploadedFile['type']) ? $uploadedFile['type'] : null, + isset($uploadedFile['size']) ? $uploadedFile['size'] : null, + $uploadedFile['error'], + true + ); + } else { + $subArray = []; + foreach ($uploadedFile['error'] as $fileIdx => $error) { + // normalise subarray and re-parse to move the input's keyname up a level + $subArray[$fileIdx]['name'] = $uploadedFile['name'][$fileIdx]; + $subArray[$fileIdx]['type'] = $uploadedFile['type'][$fileIdx]; + $subArray[$fileIdx]['tmp_name'] = $uploadedFile['tmp_name'][$fileIdx]; + $subArray[$fileIdx]['error'] = $uploadedFile['error'][$fileIdx]; + $subArray[$fileIdx]['size'] = $uploadedFile['size'][$fileIdx]; + + $parsed[$field] = static::parseUploadedFiles($subArray); + } + } + } + + return $parsed; + } + + /** + * Construct a new UploadedFile instance. + * + * @param string $file The full path to the uploaded file provided by the client. + * @param string|null $name The file name. + * @param string|null $type The file media type. + * @param int|null $size The file size in bytes. + * @param int $error The UPLOAD_ERR_XXX code representing the status of the upload. + * @param bool $sapi Indicates if the upload is in a SAPI environment. + */ + public function __construct($file, $name = null, $type = null, $size = null, $error = UPLOAD_ERR_OK, $sapi = false) + { + $this->file = $file; + $this->name = $name; + $this->type = $type; + $this->size = $size; + $this->error = $error; + $this->sapi = $sapi; + } + + /** + * Retrieve a stream representing the uploaded file. + * + * This method MUST return a StreamInterface instance, representing the + * uploaded file. The purpose of this method is to allow utilizing native PHP + * stream functionality to manipulate the file upload, such as + * stream_copy_to_stream() (though the result will need to be decorated in a + * native PHP stream wrapper to work with such functions). + * + * If the moveTo() method has been called previously, this method MUST raise + * an exception. + * + * @return StreamInterface Stream representation of the uploaded file. + * @throws \RuntimeException in cases when no stream is available or can be + * created. + */ + public function getStream() + { + if ($this->moved) { + throw new \RuntimeException(sprintf('Uploaded file %1s has already been moved', $this->name)); + } + if ($this->stream === null) { + $this->stream = new Stream(fopen($this->file, 'r')); + } + + return $this->stream; + } + + /** + * Move the uploaded file to a new location. + * + * Use this method as an alternative to move_uploaded_file(). This method is + * guaranteed to work in both SAPI and non-SAPI environments. + * Implementations must determine which environment they are in, and use the + * appropriate method (move_uploaded_file(), rename(), or a stream + * operation) to perform the operation. + * + * $targetPath may be an absolute path, or a relative path. If it is a + * relative path, resolution should be the same as used by PHP's rename() + * function. + * + * The original file or stream MUST be removed on completion. + * + * If this method is called more than once, any subsequent calls MUST raise + * an exception. + * + * When used in an SAPI environment where $_FILES is populated, when writing + * files via moveTo(), is_uploaded_file() and move_uploaded_file() SHOULD be + * used to ensure permissions and upload status are verified correctly. + * + * If you wish to move to a stream, use getStream(), as SAPI operations + * cannot guarantee writing to stream destinations. + * + * @see http://php.net/is_uploaded_file + * @see http://php.net/move_uploaded_file + * + * @param string $targetPath Path to which to move the uploaded file. + * + * @throws InvalidArgumentException if the $path specified is invalid. + * @throws RuntimeException on any error during the move operation, or on + * the second or subsequent call to the method. + */ + public function moveTo($targetPath) + { + if ($this->moved) { + throw new RuntimeException('Uploaded file already moved'); + } + + if (!is_writable(dirname($targetPath))) { + throw new InvalidArgumentException('Upload target path is not writable'); + } + + $targetIsStream = strpos($targetPath, '://') > 0; + if ($targetIsStream) { + if (!copy($this->file, $targetPath)) { + throw new RuntimeException(sprintf('Error moving uploaded file %1s to %2s', $this->name, $targetPath)); + } + if (!unlink($this->file)) { + throw new RuntimeException(sprintf('Error removing uploaded file %1s', $this->name)); + } + } elseif ($this->sapi) { + if (!is_uploaded_file($this->file)) { + throw new RuntimeException(sprintf('%1s is not a valid uploaded file', $this->file)); + } + + if (!move_uploaded_file($this->file, $targetPath)) { + throw new RuntimeException(sprintf('Error moving uploaded file %1s to %2s', $this->name, $targetPath)); + } + } else { + if (!rename($this->file, $targetPath)) { + throw new RuntimeException(sprintf('Error moving uploaded file %1s to %2s', $this->name, $targetPath)); + } + } + + $this->moved = true; + } + + /** + * Retrieve the error associated with the uploaded file. + * + * The return value MUST be one of PHP's UPLOAD_ERR_XXX constants. + * + * If the file was uploaded successfully, this method MUST return + * UPLOAD_ERR_OK. + * + * Implementations SHOULD return the value stored in the "error" key of + * the file in the $_FILES array. + * + * @see http://php.net/manual/en/features.file-upload.errors.php + * + * @return int One of PHP's UPLOAD_ERR_XXX constants. + */ + public function getError() + { + return $this->error; + } + + /** + * Retrieve the filename sent by the client. + * + * Do not trust the value returned by this method. A client could send + * a malicious filename with the intention to corrupt or hack your + * application. + * + * Implementations SHOULD return the value stored in the "name" key of + * the file in the $_FILES array. + * + * @return string|null The filename sent by the client or null if none + * was provided. + */ + public function getClientFilename() + { + return $this->name; + } + + /** + * Retrieve the media type sent by the client. + * + * Do not trust the value returned by this method. A client could send + * a malicious media type with the intention to corrupt or hack your + * application. + * + * Implementations SHOULD return the value stored in the "type" key of + * the file in the $_FILES array. + * + * @return string|null The media type sent by the client or null if none + * was provided. + */ + public function getClientMediaType() + { + return $this->type; + } + + /** + * Retrieve the file size. + * + * Implementations SHOULD return the value stored in the "size" key of + * the file in the $_FILES array if available, as PHP calculates this based + * on the actual size transmitted. + * + * @return int|null The file size in bytes or null if unknown. + */ + public function getSize() + { + return $this->size; + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Uri.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Uri.php new file mode 100644 index 000000000000..27b1d0d59389 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Http/Uri.php @@ -0,0 +1,821 @@ +scheme = $this->filterScheme($scheme); + $this->host = $host; + $this->port = $this->filterPort($port); + $this->path = empty($path) ? '/' : $this->filterPath($path); + $this->query = $this->filterQuery($query); + $this->fragment = $this->filterQuery($fragment); + $this->user = $user; + $this->password = $password; + } + + /** + * Create new Uri from string. + * + * @param string $uri Complete Uri string + * (i.e., https://user:pass@host:443/path?query). + * + * @return self + */ + public static function createFromString($uri) + { + if (!is_string($uri) && !method_exists($uri, '__toString')) { + throw new InvalidArgumentException('Uri must be a string'); + } + + $parts = parse_url($uri); + $scheme = isset($parts['scheme']) ? $parts['scheme'] : ''; + $user = isset($parts['user']) ? $parts['user'] : ''; + $pass = isset($parts['pass']) ? $parts['pass'] : ''; + $host = isset($parts['host']) ? $parts['host'] : ''; + $port = isset($parts['port']) ? $parts['port'] : null; + $path = isset($parts['path']) ? $parts['path'] : ''; + $query = isset($parts['query']) ? $parts['query'] : ''; + $fragment = isset($parts['fragment']) ? $parts['fragment'] : ''; + + return new static($scheme, $host, $port, $path, $query, $fragment, $user, $pass); + } + + /** + * Create new Uri from environment. + * + * @param Environment $env + * + * @return self + */ + public static function createFromEnvironment(Environment $env) + { + // Scheme + $isSecure = $env->get('HTTPS'); + $scheme = (empty($isSecure) || $isSecure === 'off') ? 'http' : 'https'; + + // Authority: Username and password + $username = $env->get('PHP_AUTH_USER', ''); + $password = $env->get('PHP_AUTH_PW', ''); + + // Authority: Host + if ($env->has('HTTP_HOST')) { + $host = $env->get('HTTP_HOST'); + } else { + $host = $env->get('SERVER_NAME'); + } + + // Authority: Port + $port = (int)$env->get('SERVER_PORT', 80); + if (preg_match('/^(\[[a-fA-F0-9:.]+\])(:\d+)?\z/', $host, $matches)) { + $host = $matches[1]; + + if ($matches[2]) { + $port = (int) substr($matches[2], 1); + } + } else { + $pos = strpos($host, ':'); + if ($pos !== false) { + $port = (int) substr($host, $pos + 1); + $host = strstr($host, ':', true); + } + } + + // Path + $requestScriptName = parse_url($env->get('SCRIPT_NAME'), PHP_URL_PATH); + $requestScriptDir = dirname($requestScriptName); + + // parse_url() requires a full URL. As we don't extract the domain name or scheme, + // we use a stand-in. + $requestUri = parse_url('http://example.com' . $env->get('REQUEST_URI'), PHP_URL_PATH); + + $basePath = ''; + $virtualPath = $requestUri; + if (stripos($requestUri, $requestScriptName) === 0) { + $basePath = $requestScriptName; + } elseif ($requestScriptDir !== '/' && stripos($requestUri, $requestScriptDir) === 0) { + $basePath = $requestScriptDir; + } + + if ($basePath) { + $virtualPath = ltrim(substr($requestUri, strlen($basePath)), '/'); + } + + // Query string + $queryString = $env->get('QUERY_STRING', ''); + + // Fragment + $fragment = ''; + + // Build Uri + $uri = new static($scheme, $host, $port, $virtualPath, $queryString, $fragment, $username, $password); + if ($basePath) { + $uri = $uri->withBasePath($basePath); + } + + return $uri; + } + + /******************************************************************************** + * Scheme + *******************************************************************************/ + + /** + * Retrieve the scheme component of the URI. + * + * If no scheme is present, this method MUST return an empty string. + * + * The value returned MUST be normalized to lowercase, per RFC 3986 + * Section 3.1. + * + * The trailing ":" character is not part of the scheme and MUST NOT be + * added. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.1 + * @return string The URI scheme. + */ + public function getScheme() + { + return $this->scheme; + } + + /** + * Return an instance with the specified scheme. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified scheme. + * + * Implementations MUST support the schemes "http" and "https" case + * insensitively, and MAY accommodate other schemes if required. + * + * An empty scheme is equivalent to removing the scheme. + * + * @param string $scheme The scheme to use with the new instance. + * @return self A new instance with the specified scheme. + * @throws \InvalidArgumentException for invalid or unsupported schemes. + */ + public function withScheme($scheme) + { + $scheme = $this->filterScheme($scheme); + $clone = clone $this; + $clone->scheme = $scheme; + + return $clone; + } + + /** + * Filter Uri scheme. + * + * @param string $scheme Raw Uri scheme. + * @return string + * + * @throws InvalidArgumentException If the Uri scheme is not a string. + * @throws InvalidArgumentException If Uri scheme is not "", "https", or "http". + */ + protected function filterScheme($scheme) + { + static $valid = [ + '' => true, + 'https' => true, + 'http' => true, + ]; + + if (!is_string($scheme) && !method_exists($scheme, '__toString')) { + throw new InvalidArgumentException('Uri scheme must be a string'); + } + + $scheme = str_replace('://', '', strtolower((string)$scheme)); + if (!isset($valid[$scheme])) { + throw new InvalidArgumentException('Uri scheme must be one of: "", "https", "http"'); + } + + return $scheme; + } + + /******************************************************************************** + * Authority + *******************************************************************************/ + + /** + * Retrieve the authority component of the URI. + * + * If no authority information is present, this method MUST return an empty + * string. + * + * The authority syntax of the URI is: + * + *
+     * [user-info@]host[:port]
+     * 
+ * + * If the port component is not set or is the standard port for the current + * scheme, it SHOULD NOT be included. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.2 + * @return string The URI authority, in "[user-info@]host[:port]" format. + */ + public function getAuthority() + { + $userInfo = $this->getUserInfo(); + $host = $this->getHost(); + $port = $this->getPort(); + + return ($userInfo ? $userInfo . '@' : '') . $host . ($port !== null ? ':' . $port : ''); + } + + /** + * Retrieve the user information component of the URI. + * + * If no user information is present, this method MUST return an empty + * string. + * + * If a user is present in the URI, this will return that value; + * additionally, if the password is also present, it will be appended to the + * user value, with a colon (":") separating the values. + * + * The trailing "@" character is not part of the user information and MUST + * NOT be added. + * + * @return string The URI user information, in "username[:password]" format. + */ + public function getUserInfo() + { + return $this->user . ($this->password ? ':' . $this->password : ''); + } + + /** + * Return an instance with the specified user information. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified user information. + * + * Password is optional, but the user information MUST include the + * user; an empty string for the user is equivalent to removing user + * information. + * + * @param string $user The user name to use for authority. + * @param null|string $password The password associated with $user. + * @return self A new instance with the specified user information. + */ + public function withUserInfo($user, $password = null) + { + $clone = clone $this; + $clone->user = $user; + $clone->password = $password ? $password : ''; + + return $clone; + } + + /** + * Retrieve the host component of the URI. + * + * If no host is present, this method MUST return an empty string. + * + * The value returned MUST be normalized to lowercase, per RFC 3986 + * Section 3.2.2. + * + * @see http://tools.ietf.org/html/rfc3986#section-3.2.2 + * @return string The URI host. + */ + public function getHost() + { + return $this->host; + } + + /** + * Return an instance with the specified host. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified host. + * + * An empty host value is equivalent to removing the host. + * + * @param string $host The hostname to use with the new instance. + * @return self A new instance with the specified host. + * @throws \InvalidArgumentException for invalid hostnames. + */ + public function withHost($host) + { + $clone = clone $this; + $clone->host = $host; + + return $clone; + } + + /** + * Retrieve the port component of the URI. + * + * If a port is present, and it is non-standard for the current scheme, + * this method MUST return it as an integer. If the port is the standard port + * used with the current scheme, this method SHOULD return null. + * + * If no port is present, and no scheme is present, this method MUST return + * a null value. + * + * If no port is present, but a scheme is present, this method MAY return + * the standard port for that scheme, but SHOULD return null. + * + * @return null|int The URI port. + */ + public function getPort() + { + return $this->port && !$this->hasStandardPort() ? $this->port : null; + } + + /** + * Return an instance with the specified port. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified port. + * + * Implementations MUST raise an exception for ports outside the + * established TCP and UDP port ranges. + * + * A null value provided for the port is equivalent to removing the port + * information. + * + * @param null|int $port The port to use with the new instance; a null value + * removes the port information. + * @return self A new instance with the specified port. + * @throws \InvalidArgumentException for invalid ports. + */ + public function withPort($port) + { + $port = $this->filterPort($port); + $clone = clone $this; + $clone->port = $port; + + return $clone; + } + + /** + * Does this Uri use a standard port? + * + * @return bool + */ + protected function hasStandardPort() + { + return ($this->scheme === 'http' && $this->port === 80) || ($this->scheme === 'https' && $this->port === 443); + } + + /** + * Filter Uri port. + * + * @param null|int $port The Uri port number. + * @return null|int + * + * @throws InvalidArgumentException If the port is invalid. + */ + protected function filterPort($port) + { + if (is_null($port) || (is_integer($port) && ($port >= 1 && $port <= 65535))) { + return $port; + } + + throw new InvalidArgumentException('Uri port must be null or an integer between 1 and 65535 (inclusive)'); + } + + /******************************************************************************** + * Path + *******************************************************************************/ + + /** + * Retrieve the path component of the URI. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * Normally, the empty path "" and absolute path "/" are considered equal as + * defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically + * do this normalization because in contexts with a trimmed base path, e.g. + * the front controller, this difference becomes significant. It's the task + * of the user to handle both "" and "/". + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.3. + * + * As an example, if the value should include a slash ("/") not intended as + * delimiter between path segments, that value MUST be passed in encoded + * form (e.g., "%2F") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.3 + * @return string The URI path. + */ + public function getPath() + { + return $this->path; + } + + /** + * Return an instance with the specified path. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified path. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * If the path is intended to be domain-relative rather than path relative then + * it must begin with a slash ("/"). Paths not starting with a slash ("/") + * are assumed to be relative to some base path known to the application or + * consumer. + * + * Users can provide both encoded and decoded path characters. + * Implementations ensure the correct encoding as outlined in getPath(). + * + * @param string $path The path to use with the new instance. + * @return self A new instance with the specified path. + * @throws \InvalidArgumentException for invalid paths. + */ + public function withPath($path) + { + if (!is_string($path)) { + throw new InvalidArgumentException('Uri path must be a string'); + } + + $clone = clone $this; + $clone->path = $this->filterPath($path); + + // if the path is absolute, then clear basePath + if (substr($path, 0, 1) == '/') { + $clone->basePath = ''; + } + + return $clone; + } + + /** + * Retrieve the base path segment of the URI. + * + * Note: This method is not part of the PSR-7 standard. + * + * This method MUST return a string; if no path is present it MUST return + * an empty string. + * + * @return string The base path segment of the URI. + */ + public function getBasePath() + { + return $this->basePath; + } + + /** + * Set base path. + * + * Note: This method is not part of the PSR-7 standard. + * + * @param string $basePath + * @return self + */ + public function withBasePath($basePath) + { + if (!is_string($basePath)) { + throw new InvalidArgumentException('Uri path must be a string'); + } + if (!empty($basePath)) { + $basePath = '/' . trim($basePath, '/'); // <-- Trim on both sides + } + $clone = clone $this; + + if ($basePath !== '/') { + $clone->basePath = $this->filterPath($basePath); + } + + return $clone; + } + + /** + * Filter Uri path. + * + * This method percent-encodes all reserved + * characters in the provided path string. This method + * will NOT double-encode characters that are already + * percent-encoded. + * + * @param string $path The raw uri path. + * @return string The RFC 3986 percent-encoded uri path. + * @link http://www.faqs.org/rfcs/rfc3986.html + */ + protected function filterPath($path) + { + return preg_replace_callback( + '/(?:[^a-zA-Z0-9_\-\.~:@&=\+\$,\/;%]+|%(?![A-Fa-f0-9]{2}))/', + function ($match) { + return rawurlencode($match[0]); + }, + $path + ); + } + + /******************************************************************************** + * Query + *******************************************************************************/ + + /** + * Retrieve the query string of the URI. + * + * If no query string is present, this method MUST return an empty string. + * + * The leading "?" character is not part of the query and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.4. + * + * As an example, if a value in a key/value pair of the query string should + * include an ampersand ("&") not intended as a delimiter between values, + * that value MUST be passed in encoded form (e.g., "%26") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.4 + * @return string The URI query string. + */ + public function getQuery() + { + return $this->query; + } + + /** + * Return an instance with the specified query string. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified query string. + * + * Users can provide both encoded and decoded query characters. + * Implementations ensure the correct encoding as outlined in getQuery(). + * + * An empty query string value is equivalent to removing the query string. + * + * @param string $query The query string to use with the new instance. + * @return self A new instance with the specified query string. + * @throws \InvalidArgumentException for invalid query strings. + */ + public function withQuery($query) + { + if (!is_string($query) && !method_exists($query, '__toString')) { + throw new InvalidArgumentException('Uri query must be a string'); + } + $query = ltrim((string)$query, '?'); + $clone = clone $this; + $clone->query = $this->filterQuery($query); + + return $clone; + } + + /** + * Filters the query string or fragment of a URI. + * + * @param string $query The raw uri query string. + * @return string The percent-encoded query string. + */ + protected function filterQuery($query) + { + return preg_replace_callback( + '/(?:[^a-zA-Z0-9_\-\.~!\$&\'\(\)\*\+,;=%:@\/\?]+|%(?![A-Fa-f0-9]{2}))/', + function ($match) { + return rawurlencode($match[0]); + }, + $query + ); + } + + /******************************************************************************** + * Fragment + *******************************************************************************/ + + /** + * Retrieve the fragment component of the URI. + * + * If no fragment is present, this method MUST return an empty string. + * + * The leading "#" character is not part of the fragment and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.5. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.5 + * @return string The URI fragment. + */ + public function getFragment() + { + return $this->fragment; + } + + /** + * Return an instance with the specified URI fragment. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified URI fragment. + * + * Users can provide both encoded and decoded fragment characters. + * Implementations ensure the correct encoding as outlined in getFragment(). + * + * An empty fragment value is equivalent to removing the fragment. + * + * @param string $fragment The fragment to use with the new instance. + * @return self A new instance with the specified fragment. + */ + public function withFragment($fragment) + { + if (!is_string($fragment) && !method_exists($fragment, '__toString')) { + throw new InvalidArgumentException('Uri fragment must be a string'); + } + $fragment = ltrim((string)$fragment, '#'); + $clone = clone $this; + $clone->fragment = $this->filterQuery($fragment); + + return $clone; + } + + /******************************************************************************** + * Helpers + *******************************************************************************/ + + /** + * Return the string representation as a URI reference. + * + * Depending on which components of the URI are present, the resulting + * string is either a full URI or relative reference according to RFC 3986, + * Section 4.1. The method concatenates the various components of the URI, + * using the appropriate delimiters: + * + * - If a scheme is present, it MUST be suffixed by ":". + * - If an authority is present, it MUST be prefixed by "//". + * - The path can be concatenated without delimiters. But there are two + * cases where the path has to be adjusted to make the URI reference + * valid as PHP does not allow to throw an exception in __toString(): + * - If the path is rootless and an authority is present, the path MUST + * be prefixed by "/". + * - If the path is starting with more than one "/" and no authority is + * present, the starting slashes MUST be reduced to one. + * - If a query is present, it MUST be prefixed by "?". + * - If a fragment is present, it MUST be prefixed by "#". + * + * @see http://tools.ietf.org/html/rfc3986#section-4.1 + * @return string + */ + public function __toString() + { + $scheme = $this->getScheme(); + $authority = $this->getAuthority(); + $basePath = $this->getBasePath(); + $path = $this->getPath(); + $query = $this->getQuery(); + $fragment = $this->getFragment(); + + $path = $basePath . '/' . ltrim($path, '/'); + + return ($scheme ? $scheme . ':' : '') + . ($authority ? '//' . $authority : '') + . $path + . ($query ? '?' . $query : '') + . ($fragment ? '#' . $fragment : ''); + } + + /** + * Return the fully qualified base URL. + * + * Note that this method never includes a trailing / + * + * This method is not part of PSR-7. + * + * @return string + */ + public function getBaseUrl() + { + $scheme = $this->getScheme(); + $authority = $this->getAuthority(); + $basePath = $this->getBasePath(); + + if ($authority && substr($basePath, 0, 1) !== '/') { + $basePath = $basePath . '/' . $basePath; + } + + return ($scheme ? $scheme . ':' : '') + . ($authority ? '//' . $authority : '') + . rtrim($basePath, '/'); + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Interfaces/CallableResolverInterface.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Interfaces/CallableResolverInterface.php new file mode 100644 index 000000000000..9bde59ac97a7 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Interfaces/CallableResolverInterface.php @@ -0,0 +1,27 @@ +middlewareLock) { + throw new RuntimeException('Middleware can’t be added once the stack is dequeuing'); + } + + if (is_null($this->stack)) { + $this->seedMiddlewareStack(); + } + $next = $this->stack->top(); + $this->stack[] = function (ServerRequestInterface $req, ResponseInterface $res) use ($callable, $next) { + $result = call_user_func($callable, $req, $res, $next); + if ($result instanceof ResponseInterface === false) { + throw new UnexpectedValueException( + 'Middleware must return instance of \Psr\Http\Message\ResponseInterface' + ); + } + + return $result; + }; + + return $this; + } + + /** + * Seed middleware stack with first callable + * + * @param callable $kernel The last item to run as middleware + * + * @throws RuntimeException if the stack is seeded more than once + */ + protected function seedMiddlewareStack(callable $kernel = null) + { + if (!is_null($this->stack)) { + throw new RuntimeException('MiddlewareStack can only be seeded once.'); + } + if ($kernel === null) { + $kernel = $this; + } + $this->stack = new SplStack; + $this->stack->setIteratorMode(SplDoublyLinkedList::IT_MODE_LIFO | SplDoublyLinkedList::IT_MODE_KEEP); + $this->stack[] = $kernel; + } + + /** + * Call middleware stack + * + * @param ServerRequestInterface $req A request object + * @param ResponseInterface $res A response object + * + * @return ResponseInterface + */ + public function callMiddlewareStack(ServerRequestInterface $req, ResponseInterface $res) + { + if (is_null($this->stack)) { + $this->seedMiddlewareStack(); + } + /** @var callable $start */ + $start = $this->stack->top(); + $this->middlewareLock = true; + $resp = $start($req, $res); + $this->middlewareLock = false; + return $resp; + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Routable.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Routable.php new file mode 100644 index 000000000000..4a6759fac469 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Routable.php @@ -0,0 +1,106 @@ +middleware; + } + + /** + * Get the route pattern + * + * @return string + */ + public function getPattern() + { + return $this->pattern; + } + + /** + * Set container for use with resolveCallable + * + * @param ContainerInterface $container + * + * @return self + */ + public function setContainer(ContainerInterface $container) + { + $this->container = $container; + return $this; + } + + /** + * Prepend middleware to the middleware collection + * + * @param callable|string $callable The callback routine + * + * @return static + */ + public function add($callable) + { + $this->middleware[] = new DeferredCallable($callable, $this->container); + return $this; + } + + /** + * Set the route pattern + * + * @set string + */ + public function setPattern($newPattern) + { + $this->pattern = $newPattern; + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Route.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Route.php new file mode 100644 index 000000000000..3cb4a0e28b4a --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Route.php @@ -0,0 +1,357 @@ +methods = $methods; + $this->pattern = $pattern; + $this->callable = $callable; + $this->groups = $groups; + $this->identifier = 'route' . $identifier; + } + + /** + * Finalize the route in preparation for dispatching + */ + public function finalize() + { + if ($this->finalized) { + return; + } + + $groupMiddleware = []; + foreach ($this->getGroups() as $group) { + $groupMiddleware = array_merge($group->getMiddleware(), $groupMiddleware); + } + + $this->middleware = array_merge($this->middleware, $groupMiddleware); + + foreach ($this->getMiddleware() as $middleware) { + $this->addMiddleware($middleware); + } + + $this->finalized = true; + } + + /** + * Get route callable + * + * @return callable + */ + public function getCallable() + { + return $this->callable; + } + + /** + * Get route methods + * + * @return string[] + */ + public function getMethods() + { + return $this->methods; + } + + /** + * Get parent route groups + * + * @return RouteGroup[] + */ + public function getGroups() + { + return $this->groups; + } + + /** + * Get route name + * + * @return null|string + */ + public function getName() + { + return $this->name; + } + + /** + * Get route identifier + * + * @return string + */ + public function getIdentifier() + { + return $this->identifier; + } + + /** + * Get output buffering mode + * + * @return boolean|string + */ + public function getOutputBuffering() + { + return $this->outputBuffering; + } + + /** + * Set output buffering mode + * + * One of: false, 'prepend' or 'append' + * + * @param boolean|string $mode + * + * @throws InvalidArgumentException If an unknown buffering mode is specified + */ + public function setOutputBuffering($mode) + { + if (!in_array($mode, [false, 'prepend', 'append'], true)) { + throw new InvalidArgumentException('Unknown output buffering mode'); + } + $this->outputBuffering = $mode; + } + + /** + * Set route name + * + * @param string $name + * + * @return self + * + * @throws InvalidArgumentException if the route name is not a string + */ + public function setName($name) + { + if (!is_string($name)) { + throw new InvalidArgumentException('Route name must be a string'); + } + $this->name = $name; + return $this; + } + + /** + * Set a route argument + * + * @param string $name + * @param string $value + * + * @return self + */ + public function setArgument($name, $value) + { + $this->arguments[$name] = $value; + return $this; + } + + /** + * Replace route arguments + * + * @param array $arguments + * + * @return self + */ + public function setArguments(array $arguments) + { + $this->arguments = $arguments; + return $this; + } + + /** + * Retrieve route arguments + * + * @return array + */ + public function getArguments() + { + return $this->arguments; + } + + /** + * Retrieve a specific route argument + * + * @param string $name + * @param mixed $default + * + * @return mixed + */ + public function getArgument($name, $default = null) + { + if (array_key_exists($name, $this->arguments)) { + return $this->arguments[$name]; + } + return $default; + } + + /******************************************************************************** + * Route Runner + *******************************************************************************/ + + /** + * Prepare the route for use + * + * @param ServerRequestInterface $request + * @param array $arguments + */ + public function prepare(ServerRequestInterface $request, array $arguments) + { + // Add the arguments + foreach ($arguments as $k => $v) { + $this->setArgument($k, $v); + } + } + + /** + * Run route + * + * This method traverses the middleware stack, including the route's callable + * and captures the resultant HTTP response object. It then sends the response + * back to the Application. + * + * @param ServerRequestInterface $request + * @param ResponseInterface $response + * + * @return ResponseInterface + */ + public function run(ServerRequestInterface $request, ResponseInterface $response) + { + // Finalise route now that we are about to run it + $this->finalize(); + + // Traverse middleware stack and fetch updated response + return $this->callMiddlewareStack($request, $response); + } + + /** + * Dispatch route callable against current Request and Response objects + * + * This method invokes the route object's callable. If middleware is + * registered for the route, each callable middleware is invoked in + * the order specified. + * + * @param ServerRequestInterface $request The current Request object + * @param ResponseInterface $response The current Response object + * @return \Psr\Http\Message\ResponseInterface + * @throws \Exception if the route callable throws an exception + */ + public function __invoke(ServerRequestInterface $request, ResponseInterface $response) + { + $this->callable = $this->resolveCallable($this->callable); + + /** @var InvocationStrategyInterface $handler */ + $handler = isset($this->container) ? $this->container->get('foundHandler') : new RequestResponse(); + + // invoke route callable + if ($this->outputBuffering === false) { + $newResponse = $handler($this->callable, $request, $response, $this->arguments); + } else { + try { + ob_start(); + $newResponse = $handler($this->callable, $request, $response, $this->arguments); + $output = ob_get_clean(); + } catch (Exception $e) { + ob_end_clean(); + throw $e; + } + } + + if ($newResponse instanceof ResponseInterface) { + // if route callback returns a ResponseInterface, then use it + $response = $newResponse; + } elseif (is_string($newResponse)) { + // if route callback returns a string, then append it to the response + if ($response->getBody()->isWritable()) { + $response->getBody()->write($newResponse); + } + } + + if (!empty($output) && $response->getBody()->isWritable()) { + if ($this->outputBuffering === 'prepend') { + // prepend output buffer content + $body = new Http\Body(fopen('php://temp', 'r+')); + $body->write($output . $response->getBody()); + $response = $response->withBody($body); + } elseif ($this->outputBuffering === 'append') { + // append output buffer content + $response->getBody()->write($output); + } + } + + return $response; + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/RouteGroup.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/RouteGroup.php new file mode 100644 index 000000000000..a0cdf4d47d8d --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/RouteGroup.php @@ -0,0 +1,47 @@ +pattern = $pattern; + $this->callable = $callable; + } + + /** + * Invoke the group to register any Routable objects within it. + * + * @param App $app The App to bind the callable to. + */ + public function __invoke(App $app = null) + { + $callable = $this->resolveCallable($this->callable); + if ($callable instanceof Closure && $app !== null) { + $callable = $callable->bindTo($app); + } + + $callable(); + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/Slim/Router.php b/samples/server/petstore/slim/vendor/slim/slim/Slim/Router.php new file mode 100644 index 000000000000..b9d5d132ab2f --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/Slim/Router.php @@ -0,0 +1,421 @@ +routeParser = $parser ?: new StdParser; + } + + /** + * Set the base path used in pathFor() + * + * @param string $basePath + * + * @return self + */ + public function setBasePath($basePath) + { + if (!is_string($basePath)) { + throw new InvalidArgumentException('Router basePath must be a string'); + } + + $this->basePath = $basePath; + + return $this; + } + + /** + * Set path to fast route cache file. If this is false then route caching is disabled. + * + * @param string|false $cacheFile + * + * @return self + */ + public function setCacheFile($cacheFile) + { + if (!is_string($cacheFile) && $cacheFile !== false) { + throw new InvalidArgumentException('Router cacheFile must be a string or false'); + } + + $this->cacheFile = $cacheFile; + + if ($cacheFile !== false && !is_writable(dirname($cacheFile))) { + throw new RuntimeException('Router cacheFile directory must be writable'); + } + + + return $this; + } + + /** + * Add route + * + * @param string[] $methods Array of HTTP methods + * @param string $pattern The route pattern + * @param callable $handler The route callable + * + * @return RouteInterface + * + * @throws InvalidArgumentException if the route pattern isn't a string + */ + public function map($methods, $pattern, $handler) + { + if (!is_string($pattern)) { + throw new InvalidArgumentException('Route pattern must be a string'); + } + + // Prepend parent group pattern(s) + if ($this->routeGroups) { + $pattern = $this->processGroups() . $pattern; + } + + // According to RFC methods are defined in uppercase (See RFC 7231) + $methods = array_map("strtoupper", $methods); + + // Add route + $route = new Route($methods, $pattern, $handler, $this->routeGroups, $this->routeCounter); + $this->routes[$route->getIdentifier()] = $route; + $this->routeCounter++; + + return $route; + } + + /** + * Dispatch router for HTTP request + * + * @param ServerRequestInterface $request The current HTTP request object + * + * @return array + * + * @link https://github.com/nikic/FastRoute/blob/master/src/Dispatcher.php + */ + public function dispatch(ServerRequestInterface $request) + { + $uri = '/' . ltrim($request->getUri()->getPath(), '/'); + + return $this->createDispatcher()->dispatch( + $request->getMethod(), + $uri + ); + } + + /** + * @return \FastRoute\Dispatcher + */ + protected function createDispatcher() + { + if ($this->dispatcher) { + return $this->dispatcher; + } + + $routeDefinitionCallback = function (RouteCollector $r) { + foreach ($this->getRoutes() as $route) { + $r->addRoute($route->getMethods(), $route->getPattern(), $route->getIdentifier()); + } + }; + + if ($this->cacheFile) { + $this->dispatcher = \FastRoute\cachedDispatcher($routeDefinitionCallback, [ + 'routeParser' => $this->routeParser, + 'cacheFile' => $this->cacheFile, + ]); + } else { + $this->dispatcher = \FastRoute\simpleDispatcher($routeDefinitionCallback, [ + 'routeParser' => $this->routeParser, + ]); + } + + return $this->dispatcher; + } + + /** + * @param \FastRoute\Dispatcher $dispatcher + */ + public function setDispatcher(Dispatcher $dispatcher) + { + $this->dispatcher = $dispatcher; + } + + /** + * Get route objects + * + * @return Route[] + */ + public function getRoutes() + { + return $this->routes; + } + + /** + * Get named route object + * + * @param string $name Route name + * + * @return Route + * + * @throws RuntimeException If named route does not exist + */ + public function getNamedRoute($name) + { + foreach ($this->routes as $route) { + if ($name == $route->getName()) { + return $route; + } + } + throw new RuntimeException('Named route does not exist for name: ' . $name); + } + + /** + * Remove named route + * + * @param string $name Route name + * + * @throws RuntimeException If named route does not exist + */ + public function removeNamedRoute($name) + { + $route = $this->getNamedRoute($name); + + // no exception, route exists, now remove by id + unset($this->routes[$route->getIdentifier()]); + } + + /** + * Process route groups + * + * @return string A group pattern to prefix routes with + */ + protected function processGroups() + { + $pattern = ""; + foreach ($this->routeGroups as $group) { + $pattern .= $group->getPattern(); + } + return $pattern; + } + + /** + * Add a route group to the array + * + * @param string $pattern + * @param callable $callable + * + * @return RouteGroupInterface + */ + public function pushGroup($pattern, $callable) + { + $group = new RouteGroup($pattern, $callable); + array_push($this->routeGroups, $group); + return $group; + } + + /** + * Removes the last route group from the array + * + * @return RouteGroup|bool The RouteGroup if successful, else False + */ + public function popGroup() + { + $group = array_pop($this->routeGroups); + return $group instanceof RouteGroup ? $group : false; + } + + /** + * @param $identifier + * @return \Slim\Interfaces\RouteInterface + */ + public function lookupRoute($identifier) + { + if (!isset($this->routes[$identifier])) { + throw new RuntimeException('Route not found, looks like your route cache is stale.'); + } + return $this->routes[$identifier]; + } + + /** + * Build the path for a named route excluding the base path + * + * @param string $name Route name + * @param array $data Named argument replacement data + * @param array $queryParams Optional query string parameters + * + * @return string + * + * @throws RuntimeException If named route does not exist + * @throws InvalidArgumentException If required data not provided + */ + public function relativePathFor($name, array $data = [], array $queryParams = []) + { + $route = $this->getNamedRoute($name); + $pattern = $route->getPattern(); + + $routeDatas = $this->routeParser->parse($pattern); + // $routeDatas is an array of all possible routes that can be made. There is + // one routedata for each optional parameter plus one for no optional parameters. + // + // The most specific is last, so we look for that first. + $routeDatas = array_reverse($routeDatas); + + $segments = []; + foreach ($routeDatas as $routeData) { + foreach ($routeData as $item) { + if (is_string($item)) { + // this segment is a static string + $segments[] = $item; + continue; + } + + // This segment has a parameter: first element is the name + if (!array_key_exists($item[0], $data)) { + // we don't have a data element for this segment: cancel + // testing this routeData item, so that we can try a less + // specific routeData item. + $segments = []; + $segmentName = $item[0]; + break; + } + $segments[] = $data[$item[0]]; + } + if (!empty($segments)) { + // we found all the parameters for this route data, no need to check + // less specific ones + break; + } + } + + if (empty($segments)) { + throw new InvalidArgumentException('Missing data for URL segment: ' . $segmentName); + } + $url = implode('', $segments); + + if ($queryParams) { + $url .= '?' . http_build_query($queryParams); + } + + return $url; + } + + + /** + * Build the path for a named route including the base path + * + * @param string $name Route name + * @param array $data Named argument replacement data + * @param array $queryParams Optional query string parameters + * + * @return string + * + * @throws RuntimeException If named route does not exist + * @throws InvalidArgumentException If required data not provided + */ + public function pathFor($name, array $data = [], array $queryParams = []) + { + $url = $this->relativePathFor($name, $data, $queryParams); + + if ($this->basePath) { + $url = $this->basePath . $url; + } + + return $url; + } + + /** + * Build the path for a named route. + * + * This method is deprecated. Use pathFor() from now on. + * + * @param string $name Route name + * @param array $data Named argument replacement data + * @param array $queryParams Optional query string parameters + * + * @return string + * + * @throws RuntimeException If named route does not exist + * @throws InvalidArgumentException If required data not provided + */ + public function urlFor($name, array $data = [], array $queryParams = []) + { + trigger_error('urlFor() is deprecated. Use pathFor() instead.', E_USER_DEPRECATED); + return $this->pathFor($name, $data, $queryParams); + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/composer.json b/samples/server/petstore/slim/vendor/slim/slim/composer.json new file mode 100644 index 000000000000..808eb9d38577 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/composer.json @@ -0,0 +1,57 @@ +{ + "name": "slim/slim", + "type": "library", + "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", + "keywords": ["framework","micro","api","router"], + "homepage": "http://slimframework.com", + "license": "MIT", + "authors": [ + { + "name": "Josh Lockhart", + "email": "hello@joshlockhart.com", + "homepage": "https://joshlockhart.com" + }, + { + "name": "Andrew Smith", + "email": "a.smith@silentworks.co.uk", + "homepage": "http://silentworks.co.uk" + }, + { + "name": "Rob Allen", + "email": "rob@akrabat.com", + "homepage": "http://akrabat.com" + }, + { + "name": "Gabriel Manricks", + "email": "gmanricks@me.com", + "homepage": "http://gabrielmanricks.com" + } + ], + "require": { + "php": ">=5.5.0", + "pimple/pimple": "^3.0", + "psr/http-message": "^1.0", + "nikic/fast-route": "^1.0", + "container-interop/container-interop": "^1.1" + }, + "require-dev": { + "squizlabs/php_codesniffer": "^2.5", + "phpunit/phpunit": "^4.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "autoload": { + "psr-4": { + "Slim\\": "Slim" + } + }, + "scripts": { + "test": [ + "@phpunit", + "@phpcs" + ], + "phpunit": "php vendor/bin/phpunit", + "phpcs": "php vendor/bin/phpcs" + } +} diff --git a/samples/server/petstore/slim/vendor/slim/slim/example/.htaccess b/samples/server/petstore/slim/vendor/slim/slim/example/.htaccess new file mode 100644 index 000000000000..0784bd22014a --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/example/.htaccess @@ -0,0 +1,12 @@ +# Note: see https://httpd.apache.org/docs/current/howto/htaccess.html: +# +# "You should avoid using .htaccess files completely if you have access to +# httpd main server config file. Using .htaccess files slows down your Apache +# http server. Any directive that you can include in a .htaccess file is +# better set in a Directory block, as it will have the same effect with +# better performance." + +RewriteEngine On +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule ^ index.php [QSA,L] diff --git a/samples/server/petstore/slim/vendor/slim/slim/example/README.md b/samples/server/petstore/slim/vendor/slim/slim/example/README.md new file mode 100644 index 000000000000..e4fb35982c25 --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/example/README.md @@ -0,0 +1,19 @@ +# Slim example + +1. Install composer + + ```text + $ cd Slim + $ composer install + ``` + +2. Run php server + + ```text + $ cd Slim + $ php -S localhost:8888 -t example example/index.php + ``` + +3. Open browser + + Open http://localhost:8888 in your browser and you will see 'Welcome to Slim!' diff --git a/samples/server/petstore/slim/vendor/slim/slim/example/index.php b/samples/server/petstore/slim/vendor/slim/slim/example/index.php new file mode 100644 index 000000000000..ef895f83f93b --- /dev/null +++ b/samples/server/petstore/slim/vendor/slim/slim/example/index.php @@ -0,0 +1,45 @@ +get('/', function ($request, $response, $args) { + $response->write("Welcome to Slim!"); + return $response; +}); + +$app->get('/hello[/{name}]', function ($request, $response, $args) { + $response->write("Hello, " . $args['name']); + return $response; +})->setArgument('name', 'World!'); + +/** + * Step 4: Run the Slim application + * + * This method should be called last. This executes the Slim application + * and returns the HTTP response to the HTTP client. + */ +$app->run();