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