kenken999/php
0
1<?php2require_once(getabspath("classes/cipherer.php"));3/**4 * Class for login page5 *6 */7class LoginPage extends RunnerPage8{9 public $auditObj = null;10 11 public $rememberPassword = 0;12 public $rememberMachine = 0;13 14 public $var_pUsername = "";15 public $var_pPassword = "";16 public $action = "";17 18 public $twoFactorMethod = -1;19 20 public $redirectAfterLogin = false;21 22 protected $myurl = "";23 24 public $loggedWithSP = false;25 26 protected $loggedByCredentials = false;27 public $messageType = MESSAGE_ERROR;28 29 /**30 * Second message displayed after the first one31 */32 33 public $twoFactorCode;34 35 36 protected $SMSCodeSent = false;37 38 protected $pnoneNotInQuery = false;39 40 protected $skipSecondStep = false;41 42 protected $securityPlugins;43 44 protected $controlsData = array();45 46 // tp restore session on add/edit pages47 public $restore = "";48 49 /**50 * Two-letter provider code51 */52 public $providerCode = "";53 54 55 /**56 * @constructor57 */58 function __construct(&$params)59 {60 parent::__construct($params);61 62 $this->pSetEdit = $this->pSet;63 $this->auditObj = GetAuditObject();64 65 $this->headerForms = array( "top" );66 $this->footerForms = array( "footer" );67 $this->bodyForms = array( "above-grid", "grid", "superbottom" );68 69 $this->initMyURL();70 $this->body = array( "begin" =>"", "end" => "" );71 72 $this->initSecurityPlugins();73 }74 75 protected function initSecurityPlugins()76 {77 $this->securityPlugins = Security::GetPlugins();78 79 $this->addJSSettingsForSP();80 }81 82 protected function addJSSettingsForSP()83 {84 foreach( $this->securityPlugins as $sp )85 {86 $settings = $sp->getJSSettings();87 foreach( $settings as $sKey => $s )88 {89 $this->pageData[ $sKey ] = $s;90 }91 }92 }93 94 /**95 * Set the 'connection' property96 */97 protected function setTableConnection()98 {99 global $cman;100 $this->connection = $cman->getForLogin();101 }102 103 /**104 * Set the 'cipherer' property105 */106 protected function assignCipherer()107 {108 $this->cipherer = RunnerCipherer::getForLogin();109 }110 111 /**112 *113 */114 public function process()115 {116 global $globalEvents;117 118 if( $globalEvents->exists("BeforeProcessLogin") )119 $globalEvents->BeforeProcessLogin( $this );120 121 122 $twoFactorSettings =& Security::twoFactorSettings();123 if ( !GetGlobalData( "keepLoggedIn" ) || $twoFactorSettings["available"] )124 {125 $this->hideItemType("remember_password");126 }127 128 129 $sessionLevel = Security::userSessionLevel();130 131 if( $this->action == "" ) {132 if( $sessionLevel !== LOGGED_FULL && $sessionLevel !== LOGGED_NONE ) {133 Security::clearSecuritySession();134 $sessionLevel = Security::userSessionLevel();135 }136 }137 138 139 if( ( $this->action == "change2f" || $this->action == "resendCode") && $sessionLevel === LOGGED_2F_PENDING )140 {141 $this->sendTwoFactorCode();142 }143 144 if( $this->action == "verifyCode" && $sessionLevel === LOGGED_2F_PENDING )145 {146 $this->verifyTwoFactorCode( $this->twoFactorCode );147 }148 149 if( $this->action == "resendActivation" && $sessionLevel === LOGGED_ACTIVATION_PENDING )150 {151 $this->resendActivation();152 }153 154 if( $this->action == "logout" )155 {156 $this->Logout( true );157 return;158 }159 if( $this->action == "providerlogin" )160 {161 $provider = Security::getAuthPlugin( $this->providerCode );162 if( $provider ) {163 $provider->redirectToLogin();164 exit();165 }166 return;167 }168 169 if( $this->action == "pluginLogin" )170 {171 $plugin = $this->securityPlugins[ postvalue("plugin") ];172 if( $plugin )173 {174 $this->LoginWithSP( $plugin, postvalue('plugin_token') );175 // stay and show errors176 }177 }178 179 $this->refineMessage();180 181 $this->readControls();182 183 if( $this->isActionSubmit() )184 {185 $this->doLoginRoutine();186 187 if( Security::userSessionLevel() === LOGGED_2F_PENDING ) {188 $this->sendTwoFactorCode();189 }190 }191 192 $this->prepareEditControls();193 194 // show page depending on session level and mode195 $sessionLevel = Security::userSessionLevel();196 197 // logged in ok198 if( $sessionLevel === LOGGED_FULL && !Security::isGuest()) {199 200 if( $this->mode == LOGIN_POPUP ) {201 if( !$this->restore )202 $this->pageData["redirectUrl"] = $this->getLoggedInRedirectUrl();203 } else {204 $this->redirectAfterSuccessfulLogin();205 return;206 }207 208 } else if( $sessionLevel === LOGGED_2F_PENDING ) {209 // prompt for 2factor code210 $this->hideMainLoginItems();211 $this->prepareTwoFactorMessage();212 $this->prepareTwoFactorAlternatives();213 $this->xt->assign("twofactor_code_message", true );214 $this->pageData["twoFactorMethod"] = $this->get2FactorMethod();215 216 } else if( $sessionLevel === LOGGED_ACTIVATION_PENDING ) {217 // tell about activation218 $this->hideTwoFactorItems();219 220 if( $this->action != "resendActivation" )221 $this->prepareActivationMessage();222 223 } else if( $sessionLevel === LOGGED_2FSETUP_PENDING ) {224 if( $this->mode == LOGIN_POPUP ) {225 $this->pageData["redirectUrl"] = GetTableLink("userinfo");226 } else {227 $this->redirectToUserInfo();228 return;229 }230 } else {231 // nothing, just first page access232 233 $this->hideTwoFactorItems();234 235 if( $this->mode == LOGIN_SIMPLE ) {236 // try logging in with saved credentials237 if( !isLogged() || Security::isGuest() )238 {239 Security::tryRelogin();240 }241 if( isLogged() && !Security::isGuest() )242 {243 HeaderRedirect("menu");244 return;245 }246 }247 }248 249 $_SESSION["MyURL"] = $this->myurl;250 $this->assignFieldBlocksAndLabels();251 252 if( $this->captchaExists() )253 $this->displayCaptcha();254 255 $this->addCommonJs();256 $this->addButtonHandlers();257 258 $this->fillSetCntrlMaps();259 $this->doCommonAssignments();260 261 $this->showPage();262 }263 264 protected function hideMainLoginItems()265 {266 $this->hideItemType("login_button");267 $this->hideItemType("username");268 $this->hideItemType("password");269 $this->hideItemType("username_label");270 $this->hideItemType("password_label");271 $this->hideItemType("guest_login");272 $this->hideItemType("remember_password");273 $this->hideItemType("login_external");274 $this->hideItemType("login_provider");275 276 $this->hideElement("bsloginregister");277 }278 279 protected function hideTwoFactorItems()280 {281 $this->hideItemType("auth_code");282 $this->hideItemType("verify_button");283 $this->hideItemType("resend_button");284 $this->hideItemType("remember_machine");285 $this->hideItemType("twofactor_message");286 }287 288 protected function isActionSubmit()289 {290 return $this->action == "Login";291 }292 293 /**294 * try login, create session, call events295 */296 protected function doLoginRoutine()297 {298 // block after 3 attempts feature299 if( !$this->isLoginAccessAllowed() ) {300 return false;301 }302 303 if( !$this->checkCaptcha()) {304 return false;305 }306 307 $this->readControls();308 309 if( !$this->callBeforeLoginEvent() )310 return false;311 312 $userFound = $this->createSession( $this->var_pUsername, $this->var_pPassword );313 314 if( !$userFound )315 {316 Security::auditLoginFail( $this->var_pUsername );317 $this->callAfterUnsuccessfulLoginEvent( $this->var_pUsername, $this->var_pPassword );318 return false;319 }320 321 $sessionLevel = Security::userSessionLevel();322 323 // remeber this machine is in effect, skip 2FA324 if( $sessionLevel === LOGGED_2F_PENDING ) {325 if( $this->verifyRememberMachineCookie( $_COOKIE['2ftoken']) ) {326 Security::elevateSession();327 }328 $sessionLevel = Security::userSessionLevel();329 }330 331 // successful login, call events332 if( $sessionLevel === LOGGED_FULL && !Security::isGuest() ) {333 if( $this->rememberPassword ) {334 Security::setKeepLoggedCookie( true );335 } else {336 Security::setKeepLoggedCookie( false );337 }338 Security::auditLoginSuccess();339 $this->callAfterSuccessfulLoginEvent( $this->var_pUsername, $this->var_pPassword, Security::currentUserData() );340 }341 342 return true;343 }344 345 346 /**347 * @param Boolean codeSent348 */349 protected function doAssignForSecondAuthStep( $codeSent )350 {351 $this->xt->assign("user_code", true);352 if( !$codeSent )353 $this->xt->assign("userCodeFieldClass", "rnr-hiddenblock");354 355 $this->xt->assign("user_code_buttons", true);356 if( !$codeSent )357 $this->xt->assign("verifyButtonClass", "rnr-invisible-button");358 359 if( $this->pnoneNotInQuery )360 $this->xt->assign("resendButtonClass", "rnr-invisible-button");361 }362 363 protected function prepareTwoFactorAlternatives() {364 $method = $this->get2FactorMethod();365 $twoValue = $this->twoFactorValue();366 $altMethods = Security::twoFactorEnabledMethods( $twoValue );367 foreach( $altMethods as $m => $dummy ) {368 if( $m == $method ) {369 continue;370 }371 $tag = "twofactor_altemail";372 if( $m == TWOFACTOR_APP ) {373 $tag = "twofactor_altapp";374 } else if( $m == TWOFACTOR_PHONE ) {375 $tag = "twofactor_altphone";376 }377 $this->xt->assign( $tag, true );378 }379 if( count( $altMethods ) > 1 ) {380 $this->xt->assign( "twofactor_alt_message", true );381 }382 }383 384 protected function twoFactorValue() {385 $userdata = Security::provisionalUserData();386 $twofSettings =& Security::twoFactorSettings();387 return $userdata[ $twofSettings["twoFactorField"] ];388 }389 390 protected function prepareTwoFactorMessage() {391 392 $method = $this->get2FactorMethod();393 $destination = Security::twoFactorDeliveryInfo( Security::provisionalUserData(), $method );394 $twofMessage = "";395 if( $destination["method"] == TWOFACTOR_PHONE ) {396 $twofMessage = str_replace( "%phone%", $destination["address"], "A text message with your code has been sent to: %phone%" );397 } else if( $destination["method"] == TWOFACTOR_EMAIL ) {398 $twofMessage = str_replace( "%email%", $destination["address"], "An email with your code has been sent to: %email%." );399 } else if( $destination["method"] == TWOFACTOR_APP ) {400 $twofMessage = str_replace(401 array( "%username%", "%site%" ),402 array( "<br><b>".Security::provisionalUsername()."</b>", "<b>".$destination["address"]."</b>" ),403 "Enter the code from your authentication app corresponding to %username% at %site%."404 );405 $this->hideItemType("resend_button");406 }407 $this->xt->assign('twofactor_message', $twofMessage );408 409 }410 protected function sendTwoFactorCode()411 {412 $method = $this->get2FactorMethod();413 $ret = Security::generateAndSendTwoFactorCode( $method );414 if( !$ret ) {415 return true;416 }417 if( !$ret["success"] )418 {419 $this->message = "Error sending message"." ".$ret["message"];420 $this->messageType = MESSAGE_ERROR;421 return false;422 }423 424 //return true; //?425 }426 427 protected function get2FactorMethod() {428 $method = $this->twoFactorMethod;429 $value = $this->twoFactorValue();430 if( Security::twoFactorMethodEnabled( $value, $method ) ) {431 return $method;432 }433 return Security::twoFactorPreferredMethod( $value );434 435 }436 437 438 /**439 */440 protected function verifyTwoFactorCode( $code )441 {442 if( Security::checkTwoFactorCode( $code ) ) {443 444 445 Security::elevateSession();446 $this->setRememberMachineCookie( true );447 $this->saveTwoFactorValue();448 449 Security::auditLoginSuccess();450 $this->callAfterSuccessfulLoginEvent( Security::getUserName(), '', Security::currentUserData() );451 } else {452 453 $this->setRememberMachineCookie( false );454 $this->message = "Wrong code";455 }456 }457 458 /**459 *460 */461 protected function prepareActivationMessage() {462 $this->xt->assign( "resend_activation_button", true );463 $this->message = mlang_message( "LOGIN_USER_NOT_ACTIVATED" );464 $this->messageType = MESSAGE_ERROR;465 }466 467 468 /**469 * @return String470 */471 protected function getLoggedInRedirectUrl()472 {473 if( $this->myurl )474 return $this->myurl. (strpos($this->myurl, '?') !== FALSE ? '&a=login' : '?a=login');475 476 return GetTableLink("menu");477 }478 479 480 /**481 * ????482 */483 protected function refineMessage()484 {485 if( $this->message == "expired" )486 $this->message = "Your session has expired." . " " . "Please login again.";487 elseif( $this->message == "invalidlogin" )488 $this->message = "Invalid Login";489 elseif( $this->message == "loginblocked" && strlen( $_SESSION["loginBlockMessage"] ) )490 $this->message = $_SESSION["loginBlockMessage"];491 492 if( $this->message )493 {494 $this->xt->assign("message_class", "alert-danger" );495 }496 497 unset( $_SESSION["loginBlockMessage"] );498 }499 500 /**501 *502 */503 protected function initMyURL()504 {505 $this->myurl = @$_SESSION["MyURL"];506 507 if( $this->redirectAfterLogin || $this->mode == LOGIN_POPUP || $this->action == "Login" || Security::userSessionLevel() === LOGGED_2F_PENDING ) {508 // save $this->myurl value509 }510 else511 {512 // discard. Go to menu.php after login513 $this->myurl = "";514 }515 }516 517 protected function callAfterSuccessfulLoginEvent( $username, $password = '', $userData = array() )518 {519 global $globalEvents;520 521 if( $globalEvents->exists("AfterSuccessfulLogin") )522 {523 $globalEvents->AfterSuccessfulLogin( $username, $password, $userData, $this );524 }525 }526 527 /**528 *529 */530 public function redirectAfterSuccessfulLogin()531 {532 unset( $_SESSION["MyURL"] );533 534 if( $this->myurl )535 header("Location: ".$this->myurl);536 else537 HeaderRedirect("menu");538 }539 540 541 protected function redirectToUserInfo()542 {543 HeaderRedirect("userinfo");544 }545 546 /**547 * Run AfterUnsuccessfulLogin event548 */549 public function callAfterUnsuccessfulLoginEvent( $username, $password = "" )550 {551 global $globalEvents;552 553 $message = "";554 555 // invalid login556 if( $globalEvents->exists("AfterUnsuccessfulLogin") )557 $globalEvents->AfterUnsuccessfulLogin( $username, $password, $message, $this, $this->controlsData );558 559 if( $message == "" && !$this->message )560 $this->message = "Invalid Login";561 else if( $message )562 $this->message = $message;563 }564 565 /**566 * @return Boolean567 */568 protected function isLoginAccessAllowed()569 {570 if( !$this->auditObj )571 return true;572 573 if( !$this->auditObj->LoginAccess() )574 return true;575 576 $this->message = mysprintf( "Access denied for %s minutes", array($this->auditObj->LoginAccess()) );577 $_SESSION["loginBlockMessage"] = $this->message;578 579 return false;580 }581 582 /**583 * run before login event584 * @return Boolean585 */586 protected function callBeforeLoginEvent( $data = null )587 {588 global $globalEvents;589 590 if( !$globalEvents->exists("BeforeLogin") )591 return true;592 593 $message = "";594 if( !$data ) {595 $data = &$this->controlsData;596 }597 if( !$data ) {598 $data = array();599 }600 $ret = $globalEvents->BeforeLogin( $this->var_pUsername, $this->var_pPassword, $message, $this, $data );601 602 if( $message )603 $this->message = $message;604 605 return $ret;606 }607 608 /**609 * @param String pUsername610 * @param String pPassword611 * @return Boolean612 */613 protected function logInHardcoded( $username, $password )614 {615 // username and password are hardcoded616 if( Security::verifyHardcodedLogin( $username, $password ) )617 {618 Security::createHardcodedSession();619 return true;620 }621 return false;622 }623 624 /**625 * @param String username626 */627 public function doAfterUnsuccessfulLog( $username )628 {629 if( $this->auditObj )630 {631 $this->auditObj->LogLoginFailed( $username );632 $this->auditObj->LoginUnsuccessful( $username );633 }634 }635 636 protected function createDBSesssion( $provider, $username, $password ) {637 $data = Security::fetchUserData( $username, $password, false, $this->controlsData );638 if( !$data ) {639 return false;640 }641 642 $displayName = $data[ Security::fullnameField() ];643 644 // always use username from DB to avoid upper/lower case issues645 $username = $data[ Security::usernameField() ];646 647 if( $displayName == '' ) {648 $displayName = $username;649 }650 651 // verify activation status652 if( GetGlobalData( "userRequireActivation" ) ) {653 if( $data[ GetGlobalData( "userActivationField" ) ] != 1 ) {654 Security::createProvisionalSession( $provider, LOGGED_ACTIVATION_PENDING, $username, $displayName, $data );655 return true;656 }657 }658 659 $twoFPendingLevel = Security::twoFactorPendingLevel( $data );660 if( $twoFPendingLevel != LOGGED_FULL ) {661 Security::createProvisionalSession( $provider, $twoFPendingLevel, $username, $displayName, $data );662 return true;663 }664 665 // good to go, log in666 Security::createUserSession( $provider, $username, $displayName, $data );667 return true;668 }669 670 protected function createADSesssion( $provider, $username, $password ) {671 $plugin = Security::getAuthPlugin( $provider["code"] );672 $userInfo = $plugin->login( $username, $password );673 if( !$userInfo ) {674 $this->message = $plugin->getError();675 return false;676 }677 678 $sessionLevel = LOGGED_FULL;679 if( Security::providerInDb( $provider["code"] ) ) {680 $fetchResult = Security::fetchUpdateDatabaseUser( $userInfo["userdata"], true );681 if( $fetchResult["data"] ) {682 $sessionLevel = Security::twoFactorPendingLevel( $fetchResult["data"] );683 }684 }685 686 return $plugin->createUserSession( $userInfo, false, $sessionLevel );687 }688 689 690 /**691 * try create user session692 * @param String username693 * @param String password694 * @return Boolean true when session created, false otherwise695 */696 public function createSession( $username, $password )697 {698 $provider = $this->currentProvider();699 if( !$provider ) {700 return false;701 }702 703 if( $provider["type"] == stHARDCODED ) {704 return $this->logInHardcoded( $username, $password );705 }706 707 if( $provider["type"] == stDB ) {708 return $this->createDBSesssion( $provider, $username, $password );709 }710 711 if( $provider["type"] == stAD ) {712 return $this->createADSesssion( $provider, $username, $password );713 }714 715 return true;716 }717 718 719 /**720 * Logout721 * @param Boolean redirectToLogin722 */723 public function Logout($redirectToLogin = false)724 {725 global $globalEvents;726 727 if( $this->auditObj )728 $this->auditObj->LogLogout();729 730 $username = Security::isGuest()731 ? ""732 : Security::getUserName();733 734 $logoutToken = storageGet( "logout_token_hint" );735 736 unset( $_SESSION["MyURL"] );737 738 Security::clearSecuritySession();739 740 foreach( $this->securityPlugins as $sp ) {741 $sp->onLogout();742 }743 744 if( $globalEvents->exists("AfterLogout") )745 $globalEvents->AfterLogout( $username );746 747 $authPlugin = Security::getAuthPlugin( $this->providerCode );748 749 if( $authPlugin != null && $authPlugin->hasExternalLogout() ) {750 $extRedirectUri = projectURL() . GetTableLink( "login" );751 $authPlugin->redirectToLogout( $logoutToken, $extRedirectUri );752 }753 754 // redirect to login page and show message755 if ($redirectToLogin)756 {757 header("Location: ".GetTableLink("login"));758 exit();759 }760 }761 762 /**763 * @param String url764 */765 function LogoutAndRedirect($url = "")766 {767 $this->Logout();768 769 if ($url == "")770 $url = GetTableLink("menu");771 772 header("Location: ".$url);773 exit();774 }775 776 /**777 * @return DsCommand778 */779 protected function pluginUserCommand( $externalId ) {780 $externalIdField = Security::extIdField();781 if( $externalIdField ) {782 $dc = new DsCommand();783 $dc->filter = DataCondition::FieldEquals( $externalIdField, $externalId );784 $commands[] = $dc;785 }786 }787 788 789 /**790 * @param Object $plugin - Security Plugin object791 * @param string $token - token received from third-party server792 * @param Boolean $addNewUser - add a new user into the database if none exists793 */794 public function LoginWithSP( $plugin, $token, $addNewUser = true )795 {796 $provider = Security::findProvider( $plugin->code );797 //info may contain following keys: 'id', 'name', 'email'798 $info = $plugin->getUserInfo( $token );799 if ( !$info )800 {801 $this->message = $plugin->getError();802 return false;803 }804 805 if( !$this->callBeforeLoginEvent( $info ) ) {806 return false;807 }808 809 if( Security::extIdField() ) {810 // check if the user already has a record in the users table. Create new record if needed811 $dbUserData = Security::fetchUpdateDatabaseUser( $info, $addNewUser );812 $data = $dbUserData["data"];813 if( !$data ) {814 $this->message = $dbUserData["errorMessage"] ? $dbUserData["errorMessage"] : "Database error";815 return false;816 }817 } else {818 $data = array();819 $data[ Security::emailField() ? Security::emailField() : "email" ] = $info[ "email" ];820 $data[ Security::fullnameField() ? Security::fullnameField() : "name" ] = $info[ "name" ];821 $data[ Security::userpicField() ? Security::userpicField() : "picture" ] = $info[ "picture" ];822 }823 824 storageSet( "logout_token_hint", $token );825 storageSet( "rawUserData", $info[ "raw" ] );826 $plugin->saveStorageData();827 828 $this->loggedWithSP = true;829 830 Security::createUserSession( $provider, $info["id"], $info[ "name" ], $data );831 Security::auditLoginSuccess();832 $this->callAfterSuccessfulLoginEvent( $info["id"], $data[ Security::passwordField() ], $data );833 834 return true;835 }836 837 838 /**839 * @return String840 */841 function getCaptchaId()842 {843 return "login";844 }845 846 /**847 * @param String messageText848 */849 public function setDatabaseError( $messageText )850 {851 $this->message = $messageText;852 }853 854 /**855 * calc some checksum of the two factor settings856 */857 protected function remeberMachineChecksum() {858 $twofSettings =& Security::twoFactorSettings();859 $elements = array();860 $data =& Security::currentUserData();861 if( !$data ) {862 return false;863 }864 $elements[] = $data[ $twofSettings["twoFactorField"] ];865 $elements[] = $data[ $twofSettings["phoneField"] ];866 $elements[] = $data[ $twofSettings["emailField"] ];867 $elements[] = $data[ $twofSettings["codeField"] ];868 return implode( '', $elements );869 }870 871 872 /**873 * This function is supposed to be called with $success=true after session elevation874 */875 public function setRememberMachineCookie( $success = true )876 {877 // set jwt cookie878 $twofSettings =& Security::twoFactorSettings();879 if( $success && $this->rememberMachine && $twofSettings["remember"] ) {880 $secondsIn30 = 30 * 1440 * 60;881 setProjectCookie("2ftoken", jwt_encode( array(882 "2fusername" => Security::getUserName(),883 "host" => projectHost(),884 "checksum" => getPasswordHash( $this->remeberMachineChecksum() )885 ), $secondsIn30 ), time() + $secondsIn30, true );886 } else {887 setProjectCookie("2ftoken", "", time() - 1, true );888 }889 }890 891 public function verifyRememberMachineCookie( $jwt ) {892 $twofSettings =& Security::twoFactorSettings();893 if( !$twofSettings["remember"] ) {894 return false;895 }896 $payload = jwt_verify_decode( $jwt );897 if( !$payload )898 return false;899 return $payload["2fusername"] === Security::provisionalUsername()900 && passwordVerify( $this->remeberMachineChecksum(), $payload["checksum"] );901 }902 903 904 /**905 *906 */907 public function setLangParams()908 {909 }910 911 /**912 *913 */914 protected function assignBody()915 {916 global $pagesData;917 $this->body["begin"] .= GetBaseScriptsForPage(false);918 $this->body["begin"] .= "<form method=\"post\" action='".GetTableLink("login", "", "page=".rawurlencode( $this->pageName ))."' ".919 "id=\"form".$this->id."\" name=\"form".$this->id."\">"920 ."<input type=\"hidden\" name=\"btnSubmit\" value=\"Login\">";921 $this->body["end"] .= "</form>";922 923 $this->body['end'] .= '<script>';924 $this->body['end'] .= "window.controlsMap = ".my_json_encode($this->controlsHTMLMap).";";925 $this->body['end'] .= "window.viewControlsMap = ".my_json_encode($this->viewControlsHTMLMap).";";926 $this->body['end'] .= "Runner.applyPagesData( ".my_json_encode( $pagesData )." );";927 $this->body['end'] .= "window.settings = ".my_json_encode($this->jsSettings).";</script>";928 929 $this->body["end"] .= "<script type=\"text/javascript\" src=\"".GetRootPathForResources("include/runnerJS/RunnerAll.js?41974")."\"></script>";930 $this->body["end"] .= '<script>'.$this->PrepareJS()."</script>";931 932 $this->xt->assignbyref("body", $this->body);933 }934 935 /**936 *937 */938 protected function assignSPButtons()939 {940 $this->xt->assign("facebookbutton", true);941 $this->xt->assign("google_signin", true);942 943 if( GetEmailField() )944 $this->xt->assign("fb_loginbutton_params", " data-scope=\"email\" ");945 }946 947 /**948 *949 */950 public function doCommonAssignments()951 {952 $this->xt->assign("loginlink_attrs", 'id="submitLogin'.$this->id.'"');953 954 $this->assignSPButtons();955 956 $this->setLangParams();957 958 $rememberbox_checked = "";959 if( $this->rememberPassword )960 $this->xt->assign("rememberbox_attrs", "checked" );961 962 $this->xt->assign( "guestlink_block", $this->mode == LOGIN_SIMPLE && Security::guestLoginAvailable() );963 964 $this->xt->assign("username_label", true);965 $this->xt->assign("password_label", true);966 967 968 $usernameValue = "";969 if( strlen( $this->var_pUsername ) ) {970 $usernameValue = 'value="' . runner_htmlspecialchars($this->var_pUsername) . '"';971 }972 $this->xt->assign("username_attrs", "id=\"username\" " . $usernameValue );973 $this->xt->assign("password_attrs", "id=\"password\" " );974 975 976 $guestUrl = $this->myurl && $_SESSION["MyUrlAccess"]977 ? $this->myurl978 : GetTableLink("menu");979 980 $this->xt->assign("guestlink_attrs", 'href="' . runner_htmlspecialchars($guestUrl) . '"');981 982 983 984 $this->xt->assign("main_loginfields", true);985 $this->xt->assign("signin_button", true);986 $this->xt->assign("login_logo", true );987 988 if( $this->mode == LOGIN_POPUP )989 {990 if( $this->restore && Security::userSessionLevel() === LOGGED_FULL && !Security::isGuest() ) {991 $continuebutton_attrs = 'href="#" id="continueButton"';992 993 if ( $this->getLayoutVersion() !== PD_BS_LAYOUT )994 $continuebutton_attrs .= 'style="display:none"';995 996 $this->xt->assign("continuebutton_attrs", $continuebutton_attrs);997 $this->xt->assign("continue_button", true);998 999 $this->hideMainLoginItems();1000 $this->hideTwoFactorItems();1001 $this->message = mlang_message("SUCCES_LOGGED_IN");1002 $this->messageType = MESSAGE_INFO;1003 }1004 1005 $this->xt->assign("footer", false);1006 $this->xt->assign("header", false);1007 $this->xt->assign("body", $this->body);1008 1009 $this->xt->assign("registerlink_attrs", 'name="RegisterPage" data-table="'.runner_htmlspecialchars( Security::loginTable() ).'"');1010 $this->xt->assign("forgotpasswordlink_attrs", 'name="ForgotPasswordPage"');1011 $this->xt->assign("login_logo", false );1012 }1013 1014 if( $this->message || $this->mode == LOGIN_POPUP || $this->securityPlugins )1015 {1016 $this->xt->assign("message_block", true);1017 $this->xt->assign("message", $this->message );1018 1019 if( $this->isBootstrap() )1020 $this->xt->assign("message_class", $this->messageType == MESSAGE_INFO ? "alert-success" : "alert-danger" );1021 1022 if( !$this->message )1023 $this->hideElement("message");1024 }1025 1026 $twofSettings =& Security::twoFactorSettings();1027 if( !$twofSettings["remember"] ) {1028 $this->hideItemType("remember_machine");1029 }1030 }1031 1032 /**1033 * Show the page1034 */1035 public function showPage()1036 {1037 global $globalEvents;1038 1039 if( $globalEvents->exists("BeforeShowLogin") )1040 $globalEvents->BeforeShowLogin($this->xt, $this->templatefile, $this);1041 1042 // load popup login page1043 if( $this->mode == LOGIN_POPUP ) {1044 $this->displayAJAX( $this->templatefile, $this->id + 1 );1045 exit();1046 }1047 1048 if( $this->mode == LOGIN_SIMPLE )1049 $this->assignBody();1050 1051 $this->display( $this->templatefile );1052 }1053 1054 /**1055 * @return Number1056 */1057 public static function readLoginModeFromRequest()1058 {1059 $pageMode = postvalue("mode");1060 1061 if( $pageMode == "popup" )1062 return LOGIN_POPUP;1063 1064 return LOGIN_SIMPLE;1065 }1066 1067 /**1068 * @return String1069 */1070 public static function readActionFromRequest()1071 {1072 $action = postvalue("a");1073 1074 if( $action )1075 return $action;1076 1077 return @$_POST["btnSubmit"];1078 }1079 1080 public static function readMethodFromRequest()1081 {1082 $method = postvalue("method");1083 if( $method == "" )1084 return -1;1085 return $method;1086 }1087 1088 function element2Item( $name ) {1089 if( $name == "message" ) {1090 return array( "login_message" );1091 } else if( $name == "bsloginregister" ) {1092 return array( 'login_remind', 'loginform_register_link' );1093 }1094 return parent::element2Item( $name );1095 }1096 1097 function createProjectSettings() {1098 $loginTable = Security::loginTable();1099 $table = $this->tName; // GLOBAL_PAGES1100 if( GetTableURL( $loginTable ) ) {1101 // users table is added tothe project1102 $table = $loginTable;1103 }1104 $this->pSet = new ProjectSettings($table, $this->pageType, $this->pageName, $this->pageTable );1105 /**1106 * Page type here has priority over page name. If supplied pageName is not compatible with the pageType, ignore the former.1107 * ATTENTION! It is not so in the PageSettings class. On the opposite, pageName has priority there.1108 */1109 if( $this->pSet->getPageType() !== $this->pageType ) {1110 $this->pSet = new ProjectSettings($table, $this->pageType, null, $this->pageTable );1111 }1112 }1113 1114 protected function prepareEditControls()1115 {1116 if( Security::userSessionLevel() === LOGGED_2F_PENDING )1117 return;1118 1119 /*if( $this->mode == LOGIN_EMBEDED )1120 return;*/1121 1122 $defvalues = $this->controlsData;1123 $controlFields = $this->pSet->getPageFields();1124 1125 foreach( $controlFields as $fName )1126 {1127 $parameters = array();1128 $parameters["id"] = $this->id;1129 $parameters["mode"] = "add";1130 $parameters["field"] = $fName;1131 $parameters["value"] = $defvalues[ $fName ];1132 $parameters["pageObj"] = $this;1133 1134 $this->xt->assign_function( GoodFieldName( $fName )."_editcontrol", "xt_buildeditcontrol", $parameters );1135 1136 if( $this->pSet->isUseRTE( $fName ) )1137 $_SESSION[ $this->sessionPrefix."_".$fName."_rte" ] = $defvalues[ $fName ];1138 1139 $firstElementId = $this->getControl( $fName, $this->id )->getFirstElementId();1140 if( $firstElementId )1141 $this->xt->assign("labelfor_" . goodFieldName( $fName ), $firstElementId);1142 1143 1144 $controls = array();1145 $controls["controls"] = array();1146 $controls["controls"]["id"] = $this->id;1147 $controls["controls"]["mode"] = "add";1148 $controls["controls"]["ctrlInd"] = 0;1149 $controls["controls"]["fieldName"] = $fName;1150 1151 $preload = $this->fillPreload( $fName, $controlFields, $defvalues );1152 if( $preload !== false )1153 {1154 $controls["controls"]["preloadData"] = $preload;1155 if( !$defvalues[ $fName ] && count( $preload["vals"] ) > 0 )1156 $defvalues[ $fName ] = $preload["vals"][0];1157 }1158 1159 $this->fillControlsMap( $controls );1160 $this->fillControlFlags( $fName );1161 1162 // fill special settings for a time picker1163 if( $this->pSet->getEditFormat( $fName ) == "Time" )1164 $this->fillTimePickSettings( $fName, $defvalues[ $fName ] );1165 }1166 }1167 1168 /**1169 * read values from page's controls1170 */1171 protected function readControls()1172 {1173 $avalues = array();1174 $blobfields = array();1175 $filename_values = array();1176 1177 foreach( $this->pSet->getPageFields() as $f )1178 {1179 $control = $this->getControl( $f, $this->id );1180 $control->readWebValue( $avalues, $blobfields, NULL, NULL, $filename_values );1181 }1182 1183 foreach( $avalues as $f => $value )1184 {1185 // skip blob fields1186 if( !in_array( $f, $blobfields ) )1187 $this->controlsData[ $f ] = $value;1188 }1189 }1190 1191 /**1192 * Get where from added page's controls1193 */1194 protected function getControlsWhere( $cipherer )1195 {1196 if( !$this->controlsData )1197 return "";1198 1199 $controlsWhereParts = array();1200 foreach( $this->controlsData as $f => $value )