Permalink
Browse files

Initial Commit

  • Loading branch information...
0 parents commit df76e07dc303716d5aa388a8f697287d038e603c @dongilbert dongilbert committed Nov 1, 2013
@@ -0,0 +1,4 @@
+/.idea
+/vendor
+/composer.phar
+.DS_Store
@@ -0,0 +1,19 @@
+Copyright © 2013 Don Gilbert (@dilbert4life)
+
+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.
@@ -0,0 +1,22 @@
+{
+ "name": "ugli/stack-attack",
+ "description": "Ugli StackAttack Middleware for StackPHP",
+ "license": "MIT",
+ "require": {
+ "php": ">=5.3.10",
+ "symfony/http-foundation": "~2.1",
+ "symfony/http-kernel": "~2.1"
+ },
+ "require-dev" : {
+ "silex/silex": "1.1.*@dev",
+ "stack/builder" : "1.0.*@dev",
+ "stack/callable-http-kernel": "~1.0@dev",
+ "stack/inline": "~1.0@dev",
+ "stack/run": "~1.0@dev"
+ },
+ "autoload": {
+ "psr-0": {
+ "Ugli\\StackAttack\\": "src/"
+ }
+ }
+}
@@ -0,0 +1,73 @@
+<?php
+
+namespace Ugli\StackAttack;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+
+class Attack implements HttpKernelInterface
+{
+ /**
+ * @var \Symfony\Component\HttpKernel\HttpKernelInterface
+ */
+ private $app;
+
+ /**
+ * @var string
+ */
+ private $blacklistMessage = 'Unauthorized';
+
+ /**
+ * @var FilterCollection
+ */
+ private $filters;
+
+ public function __construct(HttpKernelInterface $app, FilterCollection $filters)
+ {
+ $this->app = $app;
+ $this->filters = $filters;
+ }
+
+ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
+ {
+ if ($this->whitelisted($request)) {
+ return $this->app->handle($request, $type, $catch);
+ } elseif ($this->blacklisted($request)) {
+ return new Response($this->blacklistMessage, 401);
+ }
+
+ return $this->app->handle($request, $type, $catch);
+ }
+
+ private function whitelisted(Request $request)
+ {
+ $whitelist = $this->filters->getWhitelist();
+ if (!empty($whitelist)) {
+ foreach ($whitelist as $rule) {
+ // If the rule passes, then this is a whitelisted request.
+ if ($rule->test($request) === true) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private function blacklisted(Request $request)
+ {
+ $blacklist = $this->filters->getBlacklist();
+ if (!empty($blacklist)) {
+ foreach ($blacklist as $rule) {
+ // If the rule passes, then this is a blacklisted request.
+ if ($rule->test($request)) {
+ $this->blacklistMessage = $request->attributes->get('stackattack.match.message');
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+}
@@ -0,0 +1,33 @@
+<?php
+
+namespace Ugli\StackAttack;
+
+class FilterCollection
+{
+ protected $whitelist = array();
+ protected $blacklist = array();
+
+ public function whitelist($message, \Closure $rule)
+ {
+ $this->whitelist[] = new Filters\Whitelist($message, $rule);
+
+ return $this;
+ }
+
+ public function blacklist($message, \Closure $rule)
+ {
+ $this->blacklist[] = new Filters\Blacklist($message, $rule);
+
+ return $this;
+ }
+
+ public function getWhitelist()
+ {
+ return $this->whitelist;
+ }
+
+ public function getBlacklist()
+ {
+ return $this->blacklist;
+ }
+}
@@ -0,0 +1,8 @@
+<?php
+
+namespace Ugli\StackAttack\Filters;
+
+class Blacklist extends Check
+{
+ protected $type = 'blacklist';
+}
@@ -0,0 +1,51 @@
+<?php
+
+namespace Ugli\StackAttack\Filters;
+
+use Symfony\Component\HttpFoundation\Request;
+
+abstract class Check
+{
+ /**
+ * @var string
+ */
+ protected $message;
+
+ /**
+ * @var \Closure
+ */
+ protected $rule;
+
+ /**
+ * @var string
+ */
+ protected $type;
+
+ public function __construct($message, \Closure $rule)
+ {
+ $this->message = $message;
+ $this->rule = $rule;
+ }
+
+ public function test(Request $request)
+ {
+ if (call_user_func($this->rule, $request)) {
+ $request->attributes->set('stackattack.match.message', $this->getMessage());
+ $request->attributes->set('stackattack.match.type', $this->getType());
+
+ return true;
+ }
+
+ return false;
+ }
+
+ public function getMessage()
+ {
+ return $this->message;
+ }
+
+ public function getType()
+ {
+ return $this->type;
+ }
+}
@@ -0,0 +1,8 @@
+<?php
+
+namespace Ugli\StackAttack\Filters;
+
+class Whitelist extends Check
+{
+ protected $type = 'whitelist';
+}
@@ -0,0 +1,24 @@
+<?php
+
+namespace Stack;
+
+include_once '../vendor/autoload.php';
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Ugli\StackAttack\FilterCollection;
+
+$app = new CallableHttpKernel(function (Request $request) {
+ return new Response('Hello World!');
+});
+
+$filters = (new FilterCollection)
+ ->blacklist('Block local usage.', function (Request $request) {
+ return $request->getClientIp() === '127.0.0.1';
+ });
+
+$app = (new Builder)
+ ->push('Ugli\\StackAttack\\Attack', $filters)
+ ->resolve($app);
+
+run($app);

0 comments on commit df76e07

Please sign in to comment.