1: <?php
2:
3: /**
4: * This file is part of the Nette Framework (https://nette.org)
5: * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6: */
7:
8: namespace Nette\Forms\Controls;
9:
10: use Nette;
11:
12:
13: /**
14: * CSRF protection field.
15: */
16: class CsrfProtection extends HiddenField
17: {
18: const PROTECTION = 'Nette\Forms\Controls\CsrfProtection::validateCsrf';
19:
20: /** @var Nette\Http\Session */
21: public $session;
22:
23:
24: /**
25: * @param string
26: * @param int
27: */
28: public function __construct($message)
29: {
30: parent::__construct();
31: $this->setOmitted()
32: ->setRequired()
33: ->addRule(self::PROTECTION, $message);
34: $this->monitor(Nette\Application\UI\Presenter::class);
35: }
36:
37:
38: protected function attached($parent)
39: {
40: parent::attached($parent);
41: if (!$this->session && $parent instanceof Nette\Application\UI\Presenter) {
42: $this->session = $parent->getSession();
43: }
44: }
45:
46:
47: /**
48: * @return static
49: * @internal
50: */
51: public function setValue($value)
52: {
53: return $this;
54: }
55:
56:
57: /**
58: * Loads HTTP data.
59: * @return void
60: */
61: public function loadHttpData()
62: {
63: $this->value = $this->getHttpData(Nette\Forms\Form::DATA_TEXT);
64: }
65:
66:
67: /**
68: * @return string
69: */
70: public function getToken()
71: {
72: $session = $this->getSession()->getSection(__CLASS__);
73: if (!isset($session->token)) {
74: $session->token = Nette\Utils\Random::generate();
75: }
76: return $session->token ^ $this->getSession()->getId();
77: }
78:
79:
80: /**
81: * @return string
82: */
83: private function generateToken($random = NULL)
84: {
85: if ($random === NULL) {
86: $random = Nette\Utils\Random::generate(10);
87: }
88: return $random . base64_encode(sha1($this->getToken() . $random, TRUE));
89: }
90:
91:
92: /**
93: * Generates control's HTML element.
94: * @return Nette\Utils\Html
95: */
96: public function getControl()
97: {
98: return parent::getControl()->value($this->generateToken());
99: }
100:
101:
102: /**
103: * @return bool
104: * @internal
105: */
106: public static function validateCsrf(CsrfProtection $control)
107: {
108: $value = $control->getValue();
109: return $control->generateToken(substr($value, 0, 10)) === $value;
110: }
111:
112:
113: /********************* backend ****************d*g**/
114:
115:
116: /**
117: * @return Nette\Http\Session
118: */
119: private function getSession()
120: {
121: if (!$this->session) {
122: $this->session = new Nette\Http\Session($this->getForm()->httpRequest, new Nette\Http\Response);
123: }
124: return $this->session;
125: }
126:
127: }
128: