Yoshi2889 /
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 | * Handle sending out reminders, and checking the secret answer and question. It uses just a few functions to do this, which are: |
||
| 5 | * Simple Machines Forum (SMF) |
||
| 6 | * |
||
| 7 | * @package SMF |
||
| 8 | * @author Simple Machines http://www.simplemachines.org |
||
| 9 | * @copyright 2017 Simple Machines and individual contributors |
||
| 10 | * @license http://www.simplemachines.org/about/smf/license.php BSD |
||
| 11 | * |
||
| 12 | * @version 2.1 Beta 4 |
||
| 13 | */ |
||
| 14 | |||
| 15 | if (!defined('SMF')) |
||
| 16 | die('No direct access...'); |
||
| 17 | |||
| 18 | /** |
||
| 19 | * This is the controlling delegator |
||
| 20 | * @uses Profile language files and Reminder template |
||
| 21 | */ |
||
| 22 | function RemindMe() |
||
| 23 | { |
||
| 24 | global $txt, $context; |
||
| 25 | |||
| 26 | loadLanguage('Profile'); |
||
| 27 | loadTemplate('Reminder'); |
||
| 28 | |||
| 29 | $context['page_title'] = $txt['authentication_reminder']; |
||
| 30 | $context['robot_no_index'] = true; |
||
| 31 | |||
| 32 | // Delegation can be useful sometimes. |
||
| 33 | $subActions = array( |
||
| 34 | 'picktype' => 'RemindPick', |
||
| 35 | 'secret2' => 'SecretAnswer2', |
||
| 36 | 'setpassword' =>'setPassword', |
||
| 37 | 'setpassword2' =>'setPassword2' |
||
| 38 | ); |
||
| 39 | |||
| 40 | // Any subaction? If none, fall through to the main template, which will ask for one. |
||
| 41 | View Code Duplication | if (isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']])) |
|
| 42 | call_helper($subActions[$_REQUEST['sa']]); |
||
| 43 | |||
| 44 | // Creating a one time token. |
||
| 45 | else |
||
| 46 | createToken('remind'); |
||
| 47 | } |
||
| 48 | |||
| 49 | /** |
||
| 50 | * Allows the user to pick how they wish to be reminded |
||
| 51 | */ |
||
| 52 | function RemindPick() |
||
| 53 | { |
||
| 54 | global $context, $txt, $scripturl, $sourcedir, $user_info, $webmaster_email, $smcFunc, $language, $modSettings; |
||
| 55 | |||
| 56 | checkSession(); |
||
| 57 | validateToken('remind'); |
||
| 58 | createToken('remind'); |
||
| 59 | |||
| 60 | // Coming with a known ID? |
||
| 61 | if (!empty($_REQUEST['uid'])) |
||
| 62 | { |
||
| 63 | $where = 'id_member = {int:id_member}'; |
||
| 64 | $where_params['id_member'] = (int) $_REQUEST['uid']; |
||
| 65 | } |
||
| 66 | elseif (isset($_POST['user']) && $_POST['user'] != '') |
||
| 67 | { |
||
| 68 | $where = 'member_name = {string:member_name}'; |
||
| 69 | $where_params['member_name'] = $_POST['user']; |
||
| 70 | $where_params['email_address'] = $_POST['user']; |
||
| 71 | } |
||
| 72 | |||
| 73 | // You must enter a username/email address. |
||
| 74 | if (empty($where)) |
||
| 75 | fatal_lang_error('username_no_exist', false); |
||
| 76 | |||
| 77 | // Make sure we are not being slammed |
||
| 78 | // Don't call this if you're coming from the "Choose a reminder type" page - otherwise you'll likely get an error |
||
| 79 | if (!isset($_POST['reminder_type']) || !in_array($_POST['reminder_type'], array('email', 'secret'))) |
||
| 80 | { |
||
| 81 | spamProtection('remind'); |
||
| 82 | } |
||
| 83 | |||
| 84 | // Find the user! |
||
| 85 | $request = $smcFunc['db_query']('', ' |
||
| 86 | SELECT id_member, real_name, member_name, email_address, is_activated, validation_code, lngfile, secret_question |
||
| 87 | FROM {db_prefix}members |
||
| 88 | WHERE ' . $where . ' |
||
|
0 ignored issues
–
show
|
|||
| 89 | LIMIT 1', |
||
| 90 | $where_params |
||
|
0 ignored issues
–
show
The variable
$where_params does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
Loading history...
|
|||
| 91 | ); |
||
| 92 | // Maybe email? |
||
| 93 | if ($smcFunc['db_num_rows']($request) == 0 && empty($_REQUEST['uid'])) |
||
| 94 | { |
||
| 95 | $smcFunc['db_free_result']($request); |
||
| 96 | |||
| 97 | $request = $smcFunc['db_query']('', ' |
||
| 98 | SELECT id_member, real_name, member_name, email_address, is_activated, validation_code, lngfile, secret_question |
||
| 99 | FROM {db_prefix}members |
||
| 100 | WHERE email_address = {string:email_address} |
||
| 101 | LIMIT 1', |
||
| 102 | $where_params |
||
| 103 | ); |
||
| 104 | if ($smcFunc['db_num_rows']($request) == 0) |
||
| 105 | fatal_lang_error('no_user_with_email', false); |
||
| 106 | } |
||
| 107 | |||
| 108 | $row = $smcFunc['db_fetch_assoc']($request); |
||
| 109 | $smcFunc['db_free_result']($request); |
||
| 110 | |||
| 111 | // If the user isn't activated/approved, give them some feedback on what to do next. |
||
| 112 | if ($row['is_activated'] != 1) |
||
| 113 | { |
||
| 114 | // Awaiting approval... |
||
| 115 | if (trim($row['validation_code']) == '') |
||
| 116 | fatal_error(sprintf($txt['registration_not_approved'], $scripturl . '?action=activate;user=' . $_POST['user']), false); |
||
| 117 | else |
||
| 118 | fatal_error(sprintf($txt['registration_not_activated'], $scripturl . '?action=activate;user=' . $_POST['user']), false); |
||
| 119 | } |
||
| 120 | |||
| 121 | // You can't get emailed if you have no email address. |
||
| 122 | $row['email_address'] = trim($row['email_address']); |
||
| 123 | if ($row['email_address'] == '') |
||
| 124 | fatal_error($txt['no_reminder_email'] . '<br>' . $txt['send_email'] . ' <a href="mailto:' . $webmaster_email . '">webmaster</a> ' . $txt['to_ask_password'] . '.'); |
||
| 125 | |||
| 126 | // If they have no secret question then they can only get emailed the item, or they are requesting the email, send them an email. |
||
| 127 | if (empty($row['secret_question']) || (isset($_POST['reminder_type']) && $_POST['reminder_type'] == 'email')) |
||
| 128 | { |
||
| 129 | // Randomly generate a new password, with only alpha numeric characters that is a max length of 10 chars. |
||
| 130 | require_once($sourcedir . '/Subs-Members.php'); |
||
| 131 | $password = generateValidationCode(); |
||
| 132 | |||
| 133 | require_once($sourcedir . '/Subs-Post.php'); |
||
| 134 | $replacements = array( |
||
| 135 | 'REALNAME' => $row['real_name'], |
||
| 136 | 'REMINDLINK' => $scripturl . '?action=reminder;sa=setpassword;u=' . $row['id_member'] . ';code=' . $password, |
||
| 137 | 'IP' => $user_info['ip'], |
||
| 138 | 'MEMBERNAME' => $row['member_name'], |
||
| 139 | ); |
||
| 140 | |||
| 141 | $emaildata = loadEmailTemplate('forgot_password', $replacements, empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']); |
||
| 142 | $context['description'] = $txt['reminder_sent']; |
||
| 143 | |||
| 144 | sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], null, 'reminder', $emaildata['is_html'], 1); |
||
| 145 | |||
| 146 | // Set the password in the database. |
||
| 147 | updateMemberData($row['id_member'], array('validation_code' => substr(md5($password), 0, 10))); |
||
| 148 | |||
| 149 | // Set up the template. |
||
| 150 | $context['sub_template'] = 'sent'; |
||
| 151 | |||
| 152 | // Don't really. |
||
| 153 | return; |
||
| 154 | } |
||
| 155 | // Otherwise are ready to answer the question? |
||
| 156 | elseif (isset($_POST['reminder_type']) && $_POST['reminder_type'] == 'secret') |
||
| 157 | { |
||
| 158 | return SecretAnswerInput(); |
||
| 159 | } |
||
| 160 | |||
| 161 | // No we're here setup the context for template number 2! |
||
| 162 | $context['sub_template'] = 'reminder_pick'; |
||
| 163 | $context['current_member'] = array( |
||
| 164 | 'id' => $row['id_member'], |
||
| 165 | 'name' => $row['member_name'], |
||
| 166 | ); |
||
| 167 | } |
||
| 168 | |||
| 169 | /** |
||
| 170 | * Allows the user to set their new password |
||
| 171 | */ |
||
| 172 | function setPassword() |
||
| 173 | { |
||
| 174 | global $txt, $context; |
||
| 175 | |||
| 176 | loadLanguage('Login'); |
||
| 177 | |||
| 178 | // You need a code! |
||
| 179 | if (!isset($_REQUEST['code'])) |
||
| 180 | fatal_lang_error('no_access', false); |
||
| 181 | |||
| 182 | // Fill the context array. |
||
| 183 | $context += array( |
||
| 184 | 'page_title' => $txt['reminder_set_password'], |
||
| 185 | 'sub_template' => 'set_password', |
||
| 186 | 'code' => $_REQUEST['code'], |
||
| 187 | 'memID' => (int) $_REQUEST['u'] |
||
| 188 | ); |
||
| 189 | |||
| 190 | loadJavaScriptFile('register.js', array('defer' => false), 'smf_register'); |
||
| 191 | |||
| 192 | // Tokens! |
||
| 193 | createToken('remind-sp'); |
||
| 194 | } |
||
| 195 | |||
| 196 | /** |
||
| 197 | * Actually sets the new password |
||
| 198 | */ |
||
| 199 | function setPassword2() |
||
| 200 | { |
||
| 201 | global $context, $txt, $smcFunc, $sourcedir; |
||
| 202 | |||
| 203 | checkSession(); |
||
| 204 | validateToken('remind-sp'); |
||
| 205 | |||
| 206 | if (empty($_POST['u']) || !isset($_POST['passwrd1']) || !isset($_POST['passwrd2'])) |
||
| 207 | fatal_lang_error('no_access', false); |
||
| 208 | |||
| 209 | $_POST['u'] = (int) $_POST['u']; |
||
| 210 | |||
| 211 | if ($_POST['passwrd1'] != $_POST['passwrd2']) |
||
| 212 | fatal_lang_error('passwords_dont_match', false); |
||
| 213 | |||
| 214 | if ($_POST['passwrd1'] == '') |
||
| 215 | fatal_lang_error('no_password', false); |
||
| 216 | |||
| 217 | loadLanguage('Login'); |
||
| 218 | |||
| 219 | // Get the code as it should be from the database. |
||
| 220 | $request = $smcFunc['db_query']('', ' |
||
| 221 | SELECT validation_code, member_name, email_address, passwd_flood |
||
| 222 | FROM {db_prefix}members |
||
| 223 | WHERE id_member = {int:id_member} |
||
| 224 | AND is_activated = {int:is_activated} |
||
| 225 | AND validation_code != {string:blank_string} |
||
| 226 | LIMIT 1', |
||
| 227 | array( |
||
| 228 | 'id_member' => $_POST['u'], |
||
| 229 | 'is_activated' => 1, |
||
| 230 | 'blank_string' => '', |
||
| 231 | ) |
||
| 232 | ); |
||
| 233 | |||
| 234 | // Does this user exist at all? |
||
| 235 | if ($smcFunc['db_num_rows']($request) == 0) |
||
| 236 | fatal_lang_error('invalid_userid', false); |
||
| 237 | |||
| 238 | list ($realCode, $username, $email, $flood_value) = $smcFunc['db_fetch_row']($request); |
||
| 239 | $smcFunc['db_free_result']($request); |
||
| 240 | |||
| 241 | // Is the password actually valid? |
||
| 242 | require_once($sourcedir . '/Subs-Auth.php'); |
||
| 243 | $passwordError = validatePassword($_POST['passwrd1'], $username, array($email)); |
||
| 244 | |||
| 245 | // What - it's not? |
||
| 246 | if ($passwordError != null) |
||
|
0 ignored issues
–
show
|
|||
| 247 | fatal_lang_error('profile_error_password_' . $passwordError, false); |
||
| 248 | |||
| 249 | require_once($sourcedir . '/LogInOut.php'); |
||
| 250 | |||
| 251 | // Quit if this code is not right. |
||
| 252 | if (empty($_POST['code']) || substr($realCode, 0, 10) !== substr(md5($_POST['code']), 0, 10)) |
||
| 253 | { |
||
| 254 | // Stop brute force attacks like this. |
||
| 255 | validatePasswordFlood($_POST['u'], $flood_value, false); |
||
| 256 | |||
| 257 | fatal_error($txt['invalid_activation_code'], false); |
||
| 258 | } |
||
| 259 | |||
| 260 | // Just in case, flood control. |
||
| 261 | validatePasswordFlood($_POST['u'], $flood_value, true); |
||
| 262 | |||
| 263 | // User validated. Update the database! |
||
| 264 | updateMemberData($_POST['u'], array('validation_code' => '', 'passwd' => hash_password($username, $_POST['passwrd1']))); |
||
| 265 | |||
| 266 | call_integration_hook('integrate_reset_pass', array($username, $username, $_POST['passwrd1'])); |
||
| 267 | |||
| 268 | loadTemplate('Login'); |
||
| 269 | $context += array( |
||
| 270 | 'page_title' => $txt['reminder_password_set'], |
||
| 271 | 'sub_template' => 'login', |
||
| 272 | 'default_username' => $username, |
||
| 273 | 'default_password' => $_POST['passwrd1'], |
||
| 274 | 'never_expire' => false, |
||
| 275 | 'description' => $txt['reminder_password_set'] |
||
| 276 | ); |
||
| 277 | |||
| 278 | createToken('login'); |
||
| 279 | } |
||
| 280 | |||
| 281 | /** |
||
| 282 | * Allows the user to enter their secret answer |
||
| 283 | */ |
||
| 284 | function SecretAnswerInput() |
||
| 285 | { |
||
| 286 | global $context, $smcFunc; |
||
| 287 | |||
| 288 | checkSession(); |
||
| 289 | |||
| 290 | // Strings for the register auto javascript clever stuffy wuffy. |
||
| 291 | loadLanguage('Login'); |
||
| 292 | |||
| 293 | // Check they entered something... |
||
| 294 | if (empty($_REQUEST['uid'])) |
||
| 295 | fatal_lang_error('username_no_exist', false); |
||
| 296 | |||
| 297 | // Get the stuff.... |
||
| 298 | $request = $smcFunc['db_query']('', ' |
||
| 299 | SELECT id_member, real_name, member_name, secret_question |
||
| 300 | FROM {db_prefix}members |
||
| 301 | WHERE id_member = {int:id_member} |
||
| 302 | LIMIT 1', |
||
| 303 | array( |
||
| 304 | 'id_member' => (int) $_REQUEST['uid'], |
||
| 305 | ) |
||
| 306 | ); |
||
| 307 | if ($smcFunc['db_num_rows']($request) == 0) |
||
| 308 | fatal_lang_error('username_no_exist', false); |
||
| 309 | |||
| 310 | $row = $smcFunc['db_fetch_assoc']($request); |
||
| 311 | $smcFunc['db_free_result']($request); |
||
| 312 | |||
| 313 | // If there is NO secret question - then throw an error. |
||
| 314 | if (trim($row['secret_question']) == '') |
||
| 315 | fatal_lang_error('registration_no_secret_question', false); |
||
| 316 | |||
| 317 | // Ask for the answer... |
||
| 318 | $context['remind_user'] = $row['id_member']; |
||
| 319 | $context['remind_type'] = ''; |
||
| 320 | $context['secret_question'] = $row['secret_question']; |
||
| 321 | |||
| 322 | $context['sub_template'] = 'ask'; |
||
| 323 | createToken('remind-sai'); |
||
| 324 | loadJavaScriptFile('register.js', array('defer' => false), 'smf_register'); |
||
| 325 | } |
||
| 326 | |||
| 327 | /** |
||
| 328 | * Validates the secret answer input by the user |
||
| 329 | */ |
||
| 330 | function SecretAnswer2() |
||
| 331 | { |
||
| 332 | global $txt, $context, $smcFunc, $sourcedir; |
||
| 333 | |||
| 334 | checkSession(); |
||
| 335 | validateToken('remind-sai'); |
||
| 336 | |||
| 337 | // Hacker? How did you get this far without an email or username? |
||
| 338 | if (empty($_REQUEST['uid'])) |
||
| 339 | fatal_lang_error('username_no_exist', false); |
||
| 340 | |||
| 341 | loadLanguage('Login'); |
||
| 342 | |||
| 343 | // Get the information from the database. |
||
| 344 | $request = $smcFunc['db_query']('', ' |
||
| 345 | SELECT id_member, real_name, member_name, secret_answer, secret_question, email_address |
||
| 346 | FROM {db_prefix}members |
||
| 347 | WHERE id_member = {int:id_member} |
||
| 348 | LIMIT 1', |
||
| 349 | array( |
||
| 350 | 'id_member' => $_REQUEST['uid'], |
||
| 351 | ) |
||
| 352 | ); |
||
| 353 | if ($smcFunc['db_num_rows']($request) == 0) |
||
| 354 | fatal_lang_error('username_no_exist', false); |
||
| 355 | |||
| 356 | $row = $smcFunc['db_fetch_assoc']($request); |
||
| 357 | $smcFunc['db_free_result']($request); |
||
| 358 | |||
| 359 | // Check if the secret answer is correct. |
||
| 360 | if ($row['secret_question'] == '' || $row['secret_answer'] == '' || md5($_POST['secret_answer']) != $row['secret_answer']) |
||
| 361 | { |
||
| 362 | log_error(sprintf($txt['reminder_error'], $row['member_name']), 'user'); |
||
| 363 | fatal_lang_error('incorrect_answer', false); |
||
| 364 | } |
||
| 365 | |||
| 366 | // You can't use a blank one! |
||
| 367 | if (strlen(trim($_POST['passwrd1'])) === 0) |
||
| 368 | fatal_lang_error('no_password', false); |
||
| 369 | |||
| 370 | // They have to be the same too. |
||
| 371 | if ($_POST['passwrd1'] != $_POST['passwrd2']) |
||
| 372 | fatal_lang_error('passwords_dont_match', false); |
||
| 373 | |||
| 374 | // Make sure they have a strong enough password. |
||
| 375 | require_once($sourcedir . '/Subs-Auth.php'); |
||
| 376 | $passwordError = validatePassword($_POST['passwrd1'], $row['member_name'], array($row['email_address'])); |
||
| 377 | |||
| 378 | // Invalid? |
||
| 379 | if ($passwordError != null) |
||
|
0 ignored issues
–
show
|
|||
| 380 | fatal_lang_error('profile_error_password_' . $passwordError, false); |
||
| 381 | |||
| 382 | // Alright, so long as 'yer sure. |
||
| 383 | updateMemberData($row['id_member'], array('passwd' => hash_password($row['member_name'], $_POST['passwrd1']))); |
||
| 384 | |||
| 385 | call_integration_hook('integrate_reset_pass', array($row['member_name'], $row['member_name'], $_POST['passwrd1'])); |
||
| 386 | |||
| 387 | // Tell them it went fine. |
||
| 388 | loadTemplate('Login'); |
||
| 389 | $context += array( |
||
| 390 | 'page_title' => $txt['reminder_password_set'], |
||
| 391 | 'sub_template' => 'login', |
||
| 392 | 'default_username' => $row['member_name'], |
||
| 393 | 'default_password' => $_POST['passwrd1'], |
||
| 394 | 'never_expire' => false, |
||
| 395 | 'description' => $txt['reminder_password_set'] |
||
| 396 | ); |
||
| 397 | |||
| 398 | createToken('login'); |
||
| 399 | } |
||
| 400 | |||
| 401 | ?> |
If you define a variable conditionally, it can happen that it is not defined for all execution paths.
Let’s take a look at an example:
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.
Available Fixes
Check for existence of the variable explicitly:
Define a default value for the variable:
Add a value for the missing path: