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()->addRule(self::PROTECTION, $message);
32: $this->monitor('Nette\Application\UI\Presenter');
33: }
34:
35:
36: protected function attached($parent)
37: {
38: parent::attached($parent);
39: if (!$this->session && $parent instanceof Nette\Application\UI\Presenter) {
40: $this->session = $parent->getSession();
41: }
42: }
43:
44:
45: /**
46: * @return static
47: * @internal
48: */
49: public function setValue($value)
50: {
51: return $this;
52: }
53:
54:
55: /**
56: * Loads HTTP data.
57: * @return void
58: */
59: public function loadHttpData()
60: {
61: $this->value = $this->getHttpData(Nette\Forms\Form::DATA_TEXT);
62: }
63:
64:
65: /**
66: * @return string
67: */
68: public function getToken()
69: {
70: $session = $this->getSession()->getSection(__CLASS__);
71: if (!isset($session->token)) {
72: $session->token = Nette\Utils\Random::generate();
73: }
74: return $session->token ^ $this->getSession()->getId();
75: }
76:
77:
78: /**
79: * @return string
80: */
81: private function generateToken($random = NULL)
82: {
83: if ($random === NULL) {
84: $random = Nette\Utils\Random::generate(10);
85: }
86: return $random . base64_encode(sha1($this->getToken() . $random, TRUE));
87: }
88:
89:
90: /**
91: * Generates control's HTML element.
92: * @return Nette\Utils\Html
93: */
94: public function getControl()
95: {
96: return parent::getControl()->value($this->generateToken());
97: }
98:
99:
100: /**
101: * @return bool
102: * @internal
103: */
104: public static function validateCsrf(CsrfProtection $control)
105: {
106: $value = $control->getValue();
107: return $control->generateToken(substr($value, 0, 10)) === $value;
108: }
109:
110:
111: /********************* backend ****************d*g**/
112:
113:
114: /**
115: * @return Nette\Http\Session
116: */
117: private function getSession()
118: {
119: if (!$this->session) {
120: $this->session = new Nette\Http\Session($this->getForm()->httpRequest, new Nette\Http\Response);
121: }
122: return $this->session;
123: }
124:
125: }
126: