Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
bc77d7c0 | 4 | | Copyright CiviCRM LLC. All rights reserved. | |
6a488035 | 5 | | | |
bc77d7c0 TO |
6 | | This work is published under the GNU AGPLv3 license with some | |
7 | | permitted exceptions and without any warranty. For full license | | |
8 | | and copyright information, see https://civicrm.org/licensing | | |
6a488035 | 9 | +--------------------------------------------------------------------+ |
d25dd0ee | 10 | */ |
6a488035 TO |
11 | |
12 | /** | |
13 | * | |
14 | * @package CRM | |
ca5cec67 | 15 | * @copyright CiviCRM LLC https://civicrm.org/licensing |
6a488035 TO |
16 | * $Id$ |
17 | * | |
18 | */ | |
19 | class CRM_Core_Key { | |
518fa0ee | 20 | public static $_key = NULL; |
6a488035 | 21 | |
518fa0ee | 22 | public static $_sessionID = NULL; |
6a488035 TO |
23 | |
24 | /** | |
fe482240 | 25 | * Generate a private key per session and store in session. |
6a488035 | 26 | * |
a6c01b45 CW |
27 | * @return string |
28 | * private key for this session | |
6a488035 | 29 | */ |
00be9182 | 30 | public static function privateKey() { |
6a488035 TO |
31 | if (!self::$_key) { |
32 | $session = CRM_Core_Session::singleton(); | |
33 | self::$_key = $session->get('qfPrivateKey'); | |
34 | if (!self::$_key) { | |
35 | self::$_key = md5(uniqid(mt_rand(), TRUE)) . md5(uniqid(mt_rand(), TRUE)); | |
36 | $session->set('qfPrivateKey', self::$_key); | |
37 | } | |
38 | } | |
39 | return self::$_key; | |
40 | } | |
41 | ||
a0ee3941 EM |
42 | /** |
43 | * @return mixed|null|string | |
44 | */ | |
00be9182 | 45 | public static function sessionID() { |
6a488035 TO |
46 | if (!self::$_sessionID) { |
47 | $session = CRM_Core_Session::singleton(); | |
48 | self::$_sessionID = $session->get('qfSessionID'); | |
49 | if (!self::$_sessionID) { | |
50 | self::$_sessionID = session_id(); | |
51 | $session->set('qfSessionID', self::$_sessionID); | |
52 | } | |
53 | } | |
54 | return self::$_sessionID; | |
55 | } | |
56 | ||
57 | /** | |
58 | * Generate a form key based on form name, the current user session | |
59 | * and a private key. Modelled after drupal's form API | |
60 | * | |
c490a46a | 61 | * @param string $name |
6a0b768e TO |
62 | * @param bool $addSequence |
63 | * Should we add a unique sequence number to the end of the key. | |
6a488035 | 64 | * |
a6c01b45 CW |
65 | * @return string |
66 | * valid formID | |
6a488035 | 67 | */ |
00be9182 | 68 | public static function get($name, $addSequence = FALSE) { |
6a488035 | 69 | $privateKey = self::privateKey(); |
353ffa53 TO |
70 | $sessionID = self::sessionID(); |
71 | $key = md5($sessionID . $name . $privateKey); | |
6a488035 TO |
72 | |
73 | if ($addSequence) { | |
74 | // now generate a random number between 1 and 100K and add it to the key | |
75 | // so that we can have forms in mutiple tabs etc | |
76 | $key = $key . '_' . mt_rand(1, 10000); | |
77 | } | |
78 | return $key; | |
79 | } | |
80 | ||
81 | /** | |
fe482240 | 82 | * Validate a form key based on the form name. |
6a488035 | 83 | * |
c490a46a | 84 | * @param string $key |
6a488035 | 85 | * @param string $name |
77b97be7 EM |
86 | * @param bool $addSequence |
87 | * | |
a6c01b45 CW |
88 | * @return string |
89 | * if valid, else null | |
6a488035 | 90 | */ |
00be9182 | 91 | public static function validate($key, $name, $addSequence = FALSE) { |
6a488035 TO |
92 | if (!is_string($key)) { |
93 | return NULL; | |
94 | } | |
95 | ||
96 | if ($addSequence) { | |
97 | list($k, $t) = explode('_', $key); | |
98 | if ($t < 1 || $t > 10000) { | |
99 | return NULL; | |
100 | } | |
101 | } | |
102 | else { | |
103 | $k = $key; | |
104 | } | |
105 | ||
106 | $privateKey = self::privateKey(); | |
107 | $sessionID = self::sessionID(); | |
108 | if ($k != md5($sessionID . $name . $privateKey)) { | |
109 | return NULL; | |
110 | } | |
111 | return $key; | |
112 | } | |
113 | ||
a0ee3941 EM |
114 | /** |
115 | * @param $key | |
116 | * | |
117 | * @return bool | |
118 | */ | |
00be9182 | 119 | public static function valid($key) { |
6a488035 TO |
120 | // a valid key is a 32 digit hex number |
121 | // followed by an optional _ and a number between 1 and 10000 | |
122 | if (strpos('_', $key) !== FALSE) { | |
123 | list($hash, $seq) = explode('_', $key); | |
124 | ||
125 | // ensure seq is between 1 and 10000 | |
126 | if (!is_numeric($seq) || | |
127 | $seq < 1 || | |
128 | $seq > 10000 | |
129 | ) { | |
130 | return FALSE; | |
131 | } | |
132 | } | |
133 | else { | |
134 | $hash = $key; | |
135 | } | |
136 | ||
137 | // ensure that hash is a 32 digit hex number | |
63d76404 | 138 | return (bool) preg_match('#[0-9a-f]{32}#i', $hash); |
6a488035 | 139 | } |
96025800 | 140 | |
6a488035 | 141 | } |