1<?php 2/* 3* e107 website system 4* 5* Copyright 2008-2014 e107 Inc (e107.org) 6* Released under the terms and conditions of the 7* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) 8* 9* Interface for users who have forgotten their password 10* 11*/ 12 13 14$_E107['allow_guest'] = true; 15require_once('class2.php'); 16 17e107::coreLan('fpw'); 18 19$tp = e107::getParser(); 20 21if (USER && !getperms('0')) 22{ 23 e107::redirect(); 24 exit; 25} 26 27if($pref['fpwcode'] && extension_loaded('gd')) 28{ 29 define('USE_IMAGECODE', TRUE); 30 $sec_img = e107::getSecureImg(); 31} 32else 33{ 34 define('USE_IMAGECODE', FALSE); 35} 36 37 38class fpw_shortcodes extends e_shortcode 39{ 40 private $secImg; 41 42 function __construct() 43 { 44 parent::__construct(); 45 global $sec_img; 46 $this->secImg = $sec_img; 47 } 48 49 function sc_fpw_username($parm=null) // used when email login is disabled 50 { 51 // return "<input class='tbox' type='text' name='username' size='40' value='' maxlength='100' />"; 52 return e107::getForm()->text('username'); // $frm->userpicker()? 53 } 54 55 function sc_fpw_useremail($parm=null) 56 { 57 // return '<input class="tbox form-control" type="text" name="email" size="40" value="" maxlength="100" placeholder="Email" required="required" type="email">'; 58 // return "<input class='tbox' type='text' name='email' size='40' value='' maxlength='100' />"; 59 return e107::getForm()->email('email', '', 200, array('placeholder' => 'Email', 'required' => 'required')); 60 } 61 62 function sc_fpw_submit($parm=null) 63 { 64 // return '<button type="submit" name="pwsubmit" class="button btn btn-primary btn-block reset">'.$label.'</button>'; 65 // return "<input class='button btn btn-primary btn-block' type='submit' name='pwsubmit' value='".$label."' />"; 66 $label = deftrue('LAN_FPW_102', LAN_SUBMIT); 67 return e107::getForm()->button('pwsubmit', $label); 68 } 69 70 function sc_fpw_captcha_lan($parm=null) 71 { 72 return LAN_ENTER_CODE; 73 } 74 75 function sc_fpw_captcha_hidden($parm=null) 76 { 77 return; // no longer required - included in renderInput(); 78 } 79 80 /** 81 * @param string $parm 82 * @return mixed|null|string 83 */ 84 function sc_fpw_captcha_img($parm='') 85 { 86 if(USE_IMAGECODE) 87 { 88 return $this->secImg->renderImage(); 89 } 90 91 return null; 92 } 93 94 /** 95 * @param string $parm 96 * @return mixed|null|string 97 */ 98 function sc_fpw_captcha_input($parm=null) 99 { 100 if(USE_IMAGECODE) 101 { 102 return $this->secImg->renderInput(); 103 } 104 105 return null; 106 } 107 108 function sc_fpw_logo($parm='') 109 { 110 // Unused at the moment. 111 } 112 113 function sc_fpw_text($parm=null) 114 { 115 return deftrue('LAN_FPW_101',"Not to worry. Just enter your email address below and we'll send you an instruction email for recovery."); 116 } 117} 118 119 120if ($pref['membersonly_enabled']) 121{ 122 $sc = array ( 123 'FPW_LOGIN_LOGO' => file_exists(THEME."images/login_logo.png") ? "<img src='".THEME_ABS."images/login_logo.png' alt='' />\n" : "<img src='".e_IMAGE_ABS."logo.png' alt='' />\n" 124 ); 125 126 127 if(deftrue('BOOTSTRAP')) 128 { 129 $FPW_TABLE_HEADER = e107::getCoreTemplate('fpw','header'); 130 $FPW_TABLE_FOOTER = e107::getCoreTemplate('fpw','footer'); 131 } 132 else 133 { 134 require_once (e107::coreTemplatePath('fpw')); //correct way to load a core template. 135 } 136 137 define('e_IFRAME', true); 138 $HEAD = $tp->simpleParse($FPW_TABLE_HEADER, $sc); 139 $FOOT = $tp->simpleParse($FPW_TABLE_FOOTER, $sc); 140 141 define('e_IFRAME_HEADER', $HEAD); 142 define('e_IFRAME_FOOTER' , $FOOT); 143 144 145} 146 147$user_info = e107::getUserSession(); 148 149require_once(HEADERF); 150 151function fpw_error($txt) 152{ 153 if(deftrue('BOOTSTRAP')) 154 { 155 e107::getMessage()->addError($txt); 156 e107::getRender()->tablerender(LAN_03, e107::getMessage()->render()); 157 require_once(FOOTERF); 158 exit; 159 } 160 161 e107::getRender()->tablerender(LAN_03, "<div class='fpw-page'>".$txt."</div>", 'fpw'); 162 require_once(FOOTERF); 163 exit; 164} 165 166//the separator character used 167define('FPW_SEPARATOR', '#'); 168//$fpw_sep = '#'; 169 170 171// User has clicked on the emailed link 172if(e_QUERY) 173{ 174 // Make sure login menu is not giving any troubles 175 define('FPW_ACTIVE','TRUE'); 176 177 // Verify the password reset code syntax 178 $tmpinfo = preg_replace("#[\W_]#", "", e107::getParser()->toDB(e_QUERY, true)); // query part is a 'random' number 179 if ($tmpinfo != e_QUERY) 180 { 181 // Shouldn't be any characters that toDB() changes 182 //die(); 183 e107::getRedirect()->redirect(SITEURL); 184 } 185 186 // Verify the password reset code 187 if ($sql->select('tmp', '*', "`tmp_ip`='pwreset' AND `tmp_info` LIKE '%".FPW_SEPARATOR.$tmpinfo."' ")) 188 { 189 $row = $sql->fetch(); 190 191 // Delete the record 192 193 if(time() > (int) $row['tmp_time']) 194 { 195 $sql->delete('tmp', "`tmp_time` = ".$row['tmp_time']." AND `tmp_info` = '".$row['tmp_info']."' "); 196 e107::getMessage()->addDebug("Tmp Password Reset Entry Deleted"); 197 } 198 199 $sql->delete('tmp', "tmp_time < ".time()); // cleanup table. 200 201 list($uid, $loginName, $md5) = explode(FPW_SEPARATOR, $row['tmp_info']); 202 $loginName = $tp->toDB($loginName, true); 203 204 // This should never happen! 205 if($md5 != $tmpinfo) 206 { 207 e107::getRedirect()->redirect(SITEURL); 208 } 209 210 // Generate new temporary password 211 $pwdArray = e107::getUserSession()->resetPassword($uid,$loginName, array('return'=>'array')); 212 213 if($pwdArray === false) 214 { 215 fpw_error(LAN_214); 216 } 217 218 $newpw = $pwdArray['password']; 219 220 221 222 // Details for admin log 223 $do_log = array(); 224 $do_log['password_action'] = LAN_FPW21; 225 $do_log['user_loginname'] = $loginName; 226 $do_log['activation_code'] = $tmpinfo; 227 $do_log['user_password'] = $newpw; 228 $do_log['user_password_hash'] = $pwdArray['hash']; 229 $do_log['expires'] = date(DATE_W3C,$row['tmp_time']); 230 231 232 // Prepare new information to display to user 233 if((integer) e107::getPref('allowEmailLogin') > 0) 234 { 235 // always show email when possible 236 $sql->select('user', 'user_email', "user_id=".intval($uid)); 237 $tmp = $sql->fetch(); 238 $loginName = $tmp['user_email']; 239 $do_log['user_email'] = $tmp['user_email']; 240 unset($tmp); 241 } 242 243 $admin_log->user_audit(USER_AUDIT_PW_RES,$do_log,0,$do_log['user_name']); 244 245 if(getperms('0')) // Test Mode. 246 { 247 echo "<div class='alert alert-danger'>".print_a($do_log, true)."</div>"; 248 } 249 else 250 { 251 // Reset login cookie/session (?) 252 cookie($pref['cookie_name'], '', (time()-2592000)); 253 $_SESSION[$pref['cookie_name']] = ''; 254 } 255 256 // Display success message containing new login information 257 $txt = "<div class='fpw-message'>".LAN_FPW8."</div> 258 <table class='fpw-info'> 259 <tr><td>".LAN_218."</td><td style='font-weight:bold'>{$loginName}</td></tr> 260 <tr><td>".LAN_FPW9."</td><td style='font-weight:bold'> {$newpw}</td></tr> 261 </table> 262 <br /><br />".LAN_FPW10." <a href='".e_LOGIN."'>".LAN_LOGIN."</a>. "; // .LAN_FPW12; 263 264 e107::getMessage()->addSuccess($txt); 265 e107::getRender()->tablerender(LAN_03, e107::getMessage()->render()); 266 require_once(FOOTERF); 267 exit; 268 } 269 // The password reset code was not found 270 else 271 { 272 fpw_error(LAN_FPW7); 273 } 274} 275 276 277// Request to reset password 278if (!empty($_POST['pwsubmit'])) 279{ 280 require_once(e_HANDLER.'mail.php'); 281 282 if ($pref['fpwcode'] && extension_loaded('gd')) 283 { 284 if (!$sec_img->verify_code($_POST['rand_num'], $_POST['code_verify'])) 285 { 286 fpw_error(LAN_INVALID_CODE); 287 } 288 } 289 290 $email = $_POST['email']; 291 $clean_email = check_email($tp->toDB($_POST['email'])); 292 $clean_username = $tp->toDB(varset($_POST['username'], '')); 293 294 $query = "`user_email`='{$clean_email}' "; 295 // Allow admins to remove 'username' from fpw_template.php if they wish. 296 $query .= (isset($_POST['username'])) ? " AND `user_loginname`='{$clean_username}'" : ""; 297 298 if($sql->select('user', '*', $query)) 299 { 300 // Found user in DB 301 $row = $sql->fetch(); 302 303 // Main admin expected to be competent enough to never forget password! (And its a security check - so warn them) 304 // Sending email to admin alerting them of attempted admin password reset, and redirect user to homepage. 305 if(!getperms('0')) // disabled when testing as main-admin. 306 { 307 if (($row['user_admin'] == 1) && (($row['user_perms'] == '0') OR ($row['user_perms'] == '0.'))) 308 { 309 sendemail($pref['siteadminemail'], LAN_06, LAN_07.' ['.e107::getIPHandler()->getIP(FALSE).'] '.e107::getIPHandler()->getIP(TRUE).' '.LAN_08); 310 e107::getRedirect()->redirect(SITEURL); 311 } 312 } 313 // Banned user, or not validated 314 switch($row['user_ban']) 315 { 316 case USER_BANNED: 317 e107::getRedirect()->redirect(SITEURL); 318 break; 319 case USER_VALIDATED: 320 break; 321 default: 322 fpw_error(LAN_02.':'.$row['user_ban']); // Intentionally rather a vague message 323 exit; 324 } 325 326 // Check if password reset was already requested 327 if ($result = $sql->select('tmp', '*', "`tmp_ip` = 'pwreset' AND `tmp_info` LIKE '".$row['user_loginname'].FPW_SEPARATOR."%'")) 328 { 329 fpw_error(LAN_FPW4); 330 exit; 331 } 332 333 // Set unique reset code 334 $datekey = microtime(true); 335 $rcode = e107::getUserSession()->generateRandomString( '############' ); 336 // $rcode = crypt(($_SERVER['HTTP_USER_AGENT'] . serialize($pref). $clean_email . $datekey), e_TOKEN); 337 338 // Prepare email 339 $link = SITEURL.'fpw.php?'.$rcode; 340 $message = LAN_FPW5.' '.SITENAME.' '.LAN_FPW14.': '.e107::getIPHandler()->getIP(TRUE).".\n\n".LAN_FPW15."\n\n".LAN_FPW16."\n\n".LAN_FPW17."\n\n{$link}"; 341 342 // Set timestamp two days ahead so it doesn't get auto-deleted 343 // $deltime = time()+86400 * 2; 344 $deltime = strtotime("+ 10 minutes"); 345 346 // Insert the password reset request into the database 347 348 $insertQry = array( 349 'tmp_ip' => 'pwreset', 350 'tmp_time' => $deltime, 351 'tmp_info' => ($row['user_id'].FPW_SEPARATOR.$row['user_loginname'].FPW_SEPARATOR.$rcode) 352 ); 353 354 $sql->insert('tmp', $insertQry); 355 356 // Setup the information to log 357 $do_log['password_action'] = LAN_FPW18; 358 $do_log['user_id'] = $row['user_id']; 359 $do_log['user_name'] = $row['user_name']; 360 $do_log['user_loginname'] = $row['user_loginname']; 361 $do_log['activation_code'] = $rcode; 362 363 if(getperms('0')) 364 { 365 $message .= "\n\n<hr><strong>Caution: If you click the button below, you will follow the link the user receives in their email, and the password will actually be reset!</strong>"; // NO LAN 366 $message .= "\n\n<a class='btn btn-primary' href='".$link."'>Click to Continue with test</a>"; // NO LAN 367 $ns->tablerender("Testing Mode", nl2br($message)); 368 require_once(FOOTERF); 369 exit; 370 } 371 372 // Try to send the email 373 if(sendemail($clean_email, "".LAN_09."".SITENAME, $message)) 374 { 375 e107::getMessage()->addInfo(LAN_FPW6); 376 $do_log['password_result'] = LAN_FPW20; 377 } 378 else 379 { 380 //$text = "<div style='text-align:center'>".LAN_02."</div>"; 381 $do_log['password_result'] = LAN_FPW19; 382 fpw_error(LAN_02); 383 } 384 385 // Log to user audit log 386 e107::getAdminLog()->user_audit(USER_AUDIT_PW_RES, $do_log, $row['user_id'], $row['user_name']); 387 388 $ns->tablerender(LAN_03, $text.e107::getMessage()->render()); 389 require_once(FOOTERF); 390 exit; 391 } 392 else 393 { 394 //$text = LAN_213; 395 //$ns->tablerender(LAN_214, "<div style='text-align:center'>".$text."</div>"); 396 //e107::getMessage()->addError(LAN_213); 397 //$ns->tablerender(LAN_214, e107::getMessage()->render()); 398 fpw_error(LAN_213); 399 } 400} 401 402 403$sc = array(); // needed? 404 405 406if(deftrue('BOOTSTRAP')) 407{ 408 // TODO do we want the <form> element outside the template? 409 $FPW_TABLE = "<form method='post' action='".SITEURL."fpw.php' autocomplete='off'>"; 410 411 if(getperms('0')) 412 { 413 $FPW_TABLE.= "<div class='alert alert-danger'>Logged in as admin</div>"; 414 } 415 416 417 $FPW_TABLE .= e107::getCoreTemplate('fpw','form'); 418 $FPW_TABLE .= "</form>"; 419 $caption = deftrue('LAN_FPW_100',"Forgot your password?"); 420} 421elseif(!$FPW_TABLE) 422{ 423 require_once (e107::coreTemplatePath('fpw')); //correct way to load a core template. 424 $caption = LAN_03; 425} 426 427$sc = new fpw_shortcodes; 428 429// New Shortcode names in v2. BC Fix. 430$bcShortcodes = array('{FPW_TABLE_SECIMG_LAN}', '{FPW_TABLE_SECIMG_HIDDEN}', '{FPW_TABLE_SECIMG_SECIMG}', '{FPW_TABLE_SECIMG_TEXTBOC}'); 431$nwShortcodes = array('{FPW_CAPTCHA_LAN}', '{FPW_CAPTCHA_HIDDEN}', '{FPW_CAPTCHA_IMG}', '{FPW_CAPTCHA_INPUT}'); 432$FPW_TABLE = str_replace($bcShortcodes,$nwShortcodes,$FPW_TABLE); 433 434$text = $tp->parseTemplate($FPW_TABLE, true, $sc); 435 436// $text = $tp->simpleParse($FPW_TABLE, $sc); 437 438$ns->tablerender($caption, $text, 'fpw'); 439require_once(FOOTERF); 440 441