CsrfFilter   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 82
Duplicated Lines 9.76 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 8
loc 82
c 0
b 0
f 0
wmc 11
lcom 1
cbo 4
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
C pre() 8 45 8
A post() 0 4 1
A insertProtect() 0 10 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php /** CsrfFilterMicro */
2
3
namespace Micro\Filter;
4
5
use Micro\Base\Exception;
6
use Micro\Web\ISession;
7
use Micro\Web\RequestInjector;
8
use Micro\Web\SessionInjector;
9
use Psr\Http\Message\ServerRequestInterface;
10
11
/**
12
 * Class CsrfFilter
13
 *
14
 * @author Oleg Lunegov <[email protected]>
15
 * @link https://github.com/linpax/microphp-framework
16
 * @copyright Copyright (c) 2013 Oleg Lunegov
17
 * @license https://github.com/linpax/microphp-framework/blob/master/LICENSE
18
 * @package Micro
19
 * @subpackage Filter
20
 * @version 1.0
21
 * @since 1.0
22
 */
23
class CsrfFilter extends Filter
24
{
25
    /**
26
     * @param array $params
27
     * @return bool
28
     * @throws Exception
29
     */
30
    public function pre(array $params)
31
    {
32
        /** @var ServerRequestInterface $session */
33
        $server = (new RequestInjector)->build();
34
        /** @var ISession $session */
35
        $session = (new SessionInjector)->build();
36
37
        /** @var array $params */
38
        $params = $server->getServerParams();
39
        /** @var array $post */
40
        $post = $server->getParsedBody();
41
42
        if ($params['REQUEST_METHOD'] !== 'POST') {
43
            return true;
44
        }
45
46
        $postCSRF = $post['csrf'];
47
48 View Code Duplication
        if (!$postCSRF) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
49
            $this->result = [
50
                'redirect' => !empty($rule['redirect']) ? $rule['redirect'] : null,
0 ignored issues
show
Bug introduced by
The variable $rule seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
51
                'message' => !empty($rule['message']) ? $rule['message'] : 'Not allowed!'
52
            ];
53
54
            return false;
55
        }
56
57
        /** @var array $csrf */
58
        $csrf = $session->csrf;
0 ignored issues
show
Bug introduced by
Accessing csrf on the interface Micro\Web\ISession suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
59
60
        if (($key = in_array(md5($postCSRF), $session->csrf, true)) !== null) {
0 ignored issues
show
Bug introduced by
Accessing csrf on the interface Micro\Web\ISession suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
61
            unset($session->csrf[md5($postCSRF)]);
62
63
            $session->csrf = $csrf;
0 ignored issues
show
Bug introduced by
Accessing csrf on the interface Micro\Web\ISession suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
64
65
            return true;
66
        }
67
68
        $this->result = [
69
            'redirect' => !empty($rule['redirect']) ? $rule['redirect'] : null,
70
            'message' => !empty($rule['message']) ? $rule['message'] : 'Bad request!'
71
        ];
72
73
        return false;
74
    }
75
76
    /**
77
     * @inheritdoc
78
     */
79
    public function post(array $params)
80
    {
81
        return preg_replace_callback('/(<form[^>]*>)(.*?)(<\/form>)/m', [$this, 'insertProtect'], $params['data']);
82
    }
83
84
    /**
85
     * Insert CSRF protect into forms
86
     *
87
     * @access public
88
     *
89
     * @param array $matches Form
90
     *
91
     * @return string
92
     * @throws Exception
93
     */
94
    public function insertProtect(array $matches = [])
95
    {
96
        $gen = md5(mt_rand());
97
98
        /** @var ISession $s */
99
        $s = (new SessionInjector)->build();
100
        $s->csrf = array_merge(is_array($s->csrf) ? $s->csrf : [], [md5($gen)]);
0 ignored issues
show
Bug introduced by
Accessing csrf on the interface Micro\Web\ISession suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
101
102
        return $matches[1].'<input type="hidden" name="csrf" value="'.$gen.'" />'.$matches[2].$matches[3];
103
    }
104
}
105