Completed
Push — master ( 61b824...9bd84d )
by Aleksandr
04:57
created

Request::setChecksumKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
dl 0
loc 4
c 1
b 0
f 1
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
4
namespace carono\checksum;
5
6
use yii\helpers\ArrayHelper;
7
8
/**
9
 * Class Request
10
 *
11
 * @property mixed checksumKey
12
 * @package carono\checksum
13
 */
14
class Request extends \yii\web\Request
15
{
16
    public $checksumParam = '_checksum';
17
    public $enableChecksumValidation = true;
18
    public $redefineActiveField = true;
19
    protected $_checksumKey;
20
21
    public function getChecksumKey()
22
    {
23
        return $this->_checksumKey ?: hash("sha256", $this->cookieValidationKey);
24
    }
25
26
    public function setChecksumKey($value)
27
    {
28
        $this->_checksumKey = $value;
29
    }
30
31
    public function init()
32
    {
33
        parent::init();
34
        if ($this->redefineActiveField) {
35
            \Yii::$container->set('yii\widgets\ActiveField', 'carono\checksum\ActiveField');
36
        }
37
    }
38
39
    public function checksumIsEnabled()
40
    {
41
        return $this->enableChecksumValidation;
42
    }
43
44
    /**
45
     * @param null $clientSuppliedToken
46
     * @return bool
47
     */
48
    public function validateCsrfToken($clientSuppliedToken = null)
49
    {
50
        if ($this->isPost && $this->checksumIsEnabled()) {
51
            $post = $this->post();
52
            $checksum = ArrayHelper::remove($post, $this->checksumParam);
53
            $stack = $this->getStackByChecksum($checksum);
54
            $postPartials = Checksum::formKeyPartials($post);
55
            $stackPartials = Checksum::formKeyPartials($stack);
56
            foreach (array_diff($stackPartials, $postPartials) as $lostPartial) {
57
                list($formName, $attribute) = explode('=', $lostPartial);
58
                $post[$formName][$attribute] = '';
59
            }
60
            if (!Checksum::validate($post, $checksum, $this->checksumKey)) {
61
                return false;
62
            }
63
        }
64
        $this->clearStack();
65
        return parent::validateCsrfToken($clientSuppliedToken);
66
    }
67
68
    /**
69
     * @return string
70
     */
71
    protected function getStackKey()
72
    {
73
        return self::className() . $this->checksumParam;
74
    }
75
76
    /**
77
     * @param $widgetId
78
     * @param $modelName
79
     * @param $fieldName
80
     */
81
    public function stackField($widgetId, $modelName, $fieldName)
82
    {
83
        $key = $this->getStackKey();
84
        $data = $this->getStack();
85
        $data[$widgetId][$modelName][] = $fieldName;
86
        return \Yii::$app->session->set($key, $data);
87
    }
88
89
    /**
90
     * @param null $widgetId
91
     */
92
    public function clearStack($widgetId = null)
93
    {
94
        $key = $this->getStackKey();
95
        $data = $this->getStack();
96
        if (!is_null($widgetId)) {
97
            unset($data[$widgetId]);
98
        } else {
99
            $data = [];
100
        }
101
        return \Yii::$app->session->set($key, $data);
102
    }
103
104
    /**
105
     * @param null $widgetId
106
     * @return mixed
107
     */
108
    public function getStack($widgetId = null)
109
    {
110
        $key = self::getStackKey();
111
        $data = \Yii::$app->session->get($key, []);
112
        return is_null($widgetId) ? $data : ArrayHelper::getValue($data, $widgetId);
113
    }
114
115
    /**
116
     * @param $checksum
117
     * @return array
118
     */
119
    public function getStackByChecksum($checksum)
120
    {
121
        foreach ($this->getStack() as $item) {
122
            if (($value = ArrayHelper::getValue($item, $this->checksumParam . '.0')) && $value == $checksum) {
123
                unset($item[$this->checksumParam]);
124
                return $item;
125
            }
126
        }
127
        return [];
128
    }
129
}