albertlast /
SMF2.1
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | /** |
||
| 4 | * Implementation of PHP's session API. |
||
| 5 | * What it does: |
||
| 6 | * - it handles the session data in the database (more scalable.) |
||
| 7 | * - it uses the databaseSession_lifetime setting for garbage collection. |
||
| 8 | * - the custom session handler is set by loadSession(). |
||
| 9 | * |
||
| 10 | * Simple Machines Forum (SMF) |
||
| 11 | * |
||
| 12 | * @package SMF |
||
| 13 | * @author Simple Machines http://www.simplemachines.org |
||
| 14 | * @copyright 2017 Simple Machines and individual contributors |
||
| 15 | * @license http://www.simplemachines.org/about/smf/license.php BSD |
||
| 16 | * |
||
| 17 | * @version 2.1 Beta 4 |
||
| 18 | */ |
||
| 19 | |||
| 20 | if (!defined('SMF')) |
||
| 21 | die('No direct access...'); |
||
| 22 | |||
| 23 | /** |
||
| 24 | * Attempt to start the session, unless it already has been. |
||
| 25 | */ |
||
| 26 | function loadSession() |
||
| 27 | { |
||
| 28 | global $modSettings, $boardurl, $sc; |
||
| 29 | |||
| 30 | // Attempt to change a few PHP settings. |
||
| 31 | @ini_set('session.use_cookies', true); |
||
| 32 | @ini_set('session.use_only_cookies', false); |
||
| 33 | @ini_set('url_rewriter.tags', ''); |
||
| 34 | @ini_set('session.use_trans_sid', false); |
||
| 35 | @ini_set('arg_separator.output', '&'); |
||
| 36 | |||
| 37 | if (!empty($modSettings['globalCookies'])) |
||
| 38 | { |
||
| 39 | $parsed_url = parse_url($boardurl); |
||
| 40 | |||
| 41 | if (preg_match('~^\d{1,3}(\.\d{1,3}){3}$~', $parsed_url['host']) == 0 && preg_match('~(?:[^\.]+\.)?([^\.]{2,}\..+)\z~i', $parsed_url['host'], $parts) == 1) |
||
| 42 | @ini_set('session.cookie_domain', '.' . $parts[1]); |
||
| 43 | } |
||
| 44 | // @todo Set the session cookie path? |
||
| 45 | |||
| 46 | // If it's already been started... probably best to skip this. |
||
| 47 | if ((ini_get('session.auto_start') == 1 && !empty($modSettings['databaseSession_enable'])) || session_id() == '') |
||
| 48 | { |
||
| 49 | // Attempt to end the already-started session. |
||
| 50 | if (ini_get('session.auto_start') == 1) |
||
| 51 | session_write_close(); |
||
| 52 | |||
| 53 | // This is here to stop people from using bad junky PHPSESSIDs. |
||
| 54 | if (isset($_REQUEST[session_name()]) && preg_match('~^[A-Za-z0-9,-]{16,64}$~', $_REQUEST[session_name()]) == 0 && !isset($_COOKIE[session_name()])) |
||
| 55 | { |
||
| 56 | $session_id = md5(md5('smf_sess_' . time()) . mt_rand()); |
||
| 57 | $_REQUEST[session_name()] = $session_id; |
||
| 58 | $_GET[session_name()] = $session_id; |
||
| 59 | $_POST[session_name()] = $session_id; |
||
| 60 | } |
||
| 61 | |||
| 62 | // Use database sessions? (they don't work in 4.1.x!) |
||
| 63 | if (!empty($modSettings['databaseSession_enable'])) |
||
| 64 | { |
||
| 65 | @ini_set('session.serialize_handler', 'php'); |
||
| 66 | session_set_save_handler('sessionOpen', 'sessionClose', 'sessionRead', 'sessionWrite', 'sessionDestroy', 'sessionGC'); |
||
| 67 | @ini_set('session.gc_probability', '1'); |
||
| 68 | } |
||
| 69 | elseif (ini_get('session.gc_maxlifetime') <= 1440 && !empty($modSettings['databaseSession_lifetime'])) |
||
| 70 | @ini_set('session.gc_maxlifetime', max($modSettings['databaseSession_lifetime'], 60)); |
||
| 71 | |||
| 72 | // Use cache setting sessions? |
||
| 73 | if (empty($modSettings['databaseSession_enable']) && !empty($modSettings['cache_enable']) && php_sapi_name() != 'cli') |
||
| 74 | call_integration_hook('integrate_session_handlers'); |
||
| 75 | |||
| 76 | session_start(); |
||
| 77 | |||
| 78 | // Change it so the cache settings are a little looser than default. |
||
| 79 | if (!empty($modSettings['databaseSession_loose'])) |
||
| 80 | header('Cache-Control: private'); |
||
| 81 | } |
||
| 82 | |||
| 83 | // Set the randomly generated code. |
||
| 84 | View Code Duplication | if (!isset($_SESSION['session_var'])) |
|
|
0 ignored issues
–
show
|
|||
| 85 | { |
||
| 86 | $_SESSION['session_value'] = md5(session_id() . mt_rand()); |
||
| 87 | $_SESSION['session_var'] = substr(preg_replace('~^\d+~', '', sha1(mt_rand() . session_id() . mt_rand())), 0, mt_rand(7, 12)); |
||
| 88 | } |
||
| 89 | $sc = $_SESSION['session_value']; |
||
| 90 | } |
||
| 91 | |||
| 92 | /** |
||
| 93 | * Implementation of sessionOpen() replacing the standard open handler. |
||
| 94 | * It simply returns true. |
||
| 95 | * |
||
| 96 | * @param string $save_path The path to save the session to |
||
| 97 | * @param string $session_name The name of the session |
||
| 98 | * @return boolean Always returns true |
||
| 99 | */ |
||
| 100 | function sessionOpen($save_path, $session_name) |
||
| 101 | { |
||
| 102 | return true; |
||
| 103 | } |
||
| 104 | |||
| 105 | /** |
||
| 106 | * Implementation of sessionClose() replacing the standard close handler. |
||
| 107 | * It simply returns true. |
||
| 108 | * |
||
| 109 | * @return boolean Always returns true |
||
| 110 | */ |
||
| 111 | function sessionClose() |
||
| 112 | { |
||
| 113 | return true; |
||
| 114 | } |
||
| 115 | |||
| 116 | /** |
||
| 117 | * Implementation of sessionRead() replacing the standard read handler. |
||
| 118 | * |
||
| 119 | * @param string $session_id The session ID |
||
| 120 | * @return string The session data |
||
| 121 | */ |
||
| 122 | function sessionRead($session_id) |
||
| 123 | { |
||
| 124 | global $smcFunc; |
||
| 125 | |||
| 126 | if (preg_match('~^[A-Za-z0-9,-]{16,64}$~', $session_id) == 0) |
||
| 127 | return ''; |
||
| 128 | |||
| 129 | // Look for it in the database. |
||
| 130 | $result = $smcFunc['db_query']('', ' |
||
| 131 | SELECT data |
||
| 132 | FROM {db_prefix}sessions |
||
| 133 | WHERE session_id = {string:session_id} |
||
| 134 | LIMIT 1', |
||
| 135 | array( |
||
| 136 | 'session_id' => $session_id, |
||
| 137 | ) |
||
| 138 | ); |
||
| 139 | list ($sess_data) = $smcFunc['db_fetch_row']($result); |
||
| 140 | $smcFunc['db_free_result']($result); |
||
| 141 | |||
| 142 | return $sess_data != null ? $sess_data : ''; |
||
| 143 | } |
||
| 144 | |||
| 145 | /** |
||
| 146 | * Implementation of sessionWrite() replacing the standard write handler. |
||
| 147 | * |
||
| 148 | * @param string $session_id The session ID |
||
| 149 | * @param string $data The data to write to the session |
||
| 150 | * @return boolean Whether the info was successfully written |
||
| 151 | */ |
||
| 152 | function sessionWrite($session_id, $data) |
||
| 153 | { |
||
| 154 | global $smcFunc; |
||
| 155 | |||
| 156 | if (preg_match('~^[A-Za-z0-9,-]{16,64}$~', $session_id) == 0) |
||
| 157 | return false; |
||
| 158 | |||
| 159 | // First try to update an existing row... |
||
| 160 | $smcFunc['db_query']('', ' |
||
| 161 | UPDATE {db_prefix}sessions |
||
| 162 | SET data = {string:data}, last_update = {int:last_update} |
||
| 163 | WHERE session_id = {string:session_id}', |
||
| 164 | array( |
||
| 165 | 'last_update' => time(), |
||
| 166 | 'data' => $data, |
||
| 167 | 'session_id' => $session_id, |
||
| 168 | ) |
||
| 169 | ); |
||
| 170 | |||
| 171 | // If that didn't work, try inserting a new one. |
||
| 172 | if ($smcFunc['db_affected_rows']() == 0) |
||
| 173 | $smcFunc['db_insert']('ignore', |
||
| 174 | '{db_prefix}sessions', |
||
| 175 | array('session_id' => 'string', 'data' => 'string', 'last_update' => 'int'), |
||
| 176 | array($session_id, $data, time()), |
||
| 177 | array('session_id') |
||
| 178 | ); |
||
| 179 | |||
| 180 | return ($smcFunc['db_affected_rows']() == 0 ? false : true); |
||
| 181 | } |
||
| 182 | |||
| 183 | /** |
||
| 184 | * Implementation of sessionDestroy() replacing the standard destroy handler. |
||
| 185 | * |
||
| 186 | * @param string $session_id The session ID |
||
| 187 | * @return boolean Whether the session was successfully destroyed |
||
| 188 | */ |
||
| 189 | function sessionDestroy($session_id) |
||
| 190 | { |
||
| 191 | global $smcFunc; |
||
| 192 | |||
| 193 | if (preg_match('~^[A-Za-z0-9,-]{16,64}$~', $session_id) == 0) |
||
| 194 | return false; |
||
| 195 | |||
| 196 | // Just delete the row... |
||
| 197 | $smcFunc['db_query']('', ' |
||
| 198 | DELETE FROM {db_prefix}sessions |
||
| 199 | WHERE session_id = {string:session_id}', |
||
| 200 | array( |
||
| 201 | 'session_id' => $session_id, |
||
| 202 | ) |
||
| 203 | ); |
||
| 204 | |||
| 205 | return true; |
||
| 206 | } |
||
| 207 | |||
| 208 | /** |
||
| 209 | * Implementation of sessionGC() replacing the standard gc handler. |
||
| 210 | * Callback for garbage collection. |
||
| 211 | * |
||
| 212 | * @param int $max_lifetime The maximum lifetime (in seconds) - prevents deleting of sessions older than this |
||
| 213 | * @return boolean Whether the option was successful |
||
| 214 | */ |
||
| 215 | function sessionGC($max_lifetime) |
||
| 216 | { |
||
| 217 | global $modSettings, $smcFunc; |
||
| 218 | |||
| 219 | // Just set to the default or lower? Ignore it for a higher value. (hopefully) |
||
| 220 | if (!empty($modSettings['databaseSession_lifetime']) && ($max_lifetime <= 1440 || $modSettings['databaseSession_lifetime'] > $max_lifetime)) |
||
| 221 | $max_lifetime = max($modSettings['databaseSession_lifetime'], 60); |
||
| 222 | |||
| 223 | // Clean up after yerself ;). |
||
| 224 | $smcFunc['db_query']('', ' |
||
| 225 | DELETE FROM {db_prefix}sessions |
||
| 226 | WHERE last_update < {int:last_update}', |
||
| 227 | array( |
||
| 228 | 'last_update' => time() - $max_lifetime, |
||
| 229 | ) |
||
| 230 | ); |
||
| 231 | |||
| 232 | return ($smcFunc['db_affected_rows']() == 0 ? false : true); |
||
| 233 | } |
||
| 234 | |||
| 235 | ?> |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.