kenken999/php
0
1<?php2class ChangePasswordPage extends RunnerPage3{4 protected $pwdStrong = false;5 6 public $token = "";7 8 public $action;9 10 protected $passwordField;11 protected $usernameField;12 13 protected $auditObj = null;14 15 protected $changePwdFields;16 17 protected $changedSuccess = false;18 19 /**20 *21 */22 function __construct(&$params = "")23 {24 parent::__construct($params);25 26 if( !$this->action && !$this->checkToken() )27 {28 Security::saveRedirectURL();29 HeaderRedirect("login");30 return;31 }32 33 $this->passwordField = Security::passwordField();34 $this->usernameField = Security::usernameField();35 36 $this->auditObj = GetAuditObject();37 38 if( $this->token )39 {40 $this->changePwdFields = array("newpass", "confirm");41 // to send it back with a form (user may delete session before submit)42 $this->setProxyValue("token", $this->token);43 }44 else45 $this->changePwdFields = array("oldpass", "newpass", "confirm");46 47 // fill global password settings48 $this->pwdStrong = GetGlobalData("pwdStrong", false);49 50 if( $this->pwdStrong )51 {52 $this->settingsMap["globalSettings"]["pwdStrong"] = true;53 $this->settingsMap["globalSettings"]["pwdLen"] = GetGlobalData("pwdLen", 0);54 $this->settingsMap["globalSettings"]["pwdUnique"] = GetGlobalData("pwdUnique", 0);55 $this->settingsMap["globalSettings"]["pwdDigits"] = GetGlobalData("pwdDigits", 0);56 $this->settingsMap["globalSettings"]["pwdUpperLower"] = GetGlobalData("pwdUpperLower", false);57 }58 59 $this->headerForms = array( "top" );60 $this->footerForms = array( "footer" );61 $this->bodyForms = array( "above-grid", "grid" );62 }63 64 /**65 * Set the connection property66 */67 protected function setTableConnection()68 {69 global $cman;70 $this->connection = $cman->getForLogin();71 }72 73 /**74 *75 */76 protected function assignCipherer()77 {78 $this->cipherer = RunnerCipherer::getForLogin();79 }80 81 /**82 *83 */84 protected function setReferer()85 {86 $referer = @$_SERVER["HTTP_REFERER"] ? @$_SERVER["HTTP_REFERER"] : "";87 88 // ignore referer if from another site or if came from the same "change password" page89 $home = strtoupper( projectUrl() );90 $changePwdPage = strtoupper( projectUrl() . GetTableLink("changepwd") );91 if( substr( strtoupper( $referer ), 0 , strlen( $home ) ) != $home ||92 substr( strtoupper( $referer ), 0 , strlen( $changePwdPage ) ) == $changePwdPage ) {93 94 $referer = "";95 }96 97 if( $referer ) {98 $_SESSION["changepwd_referer"] = $referer;99 }100 if( !$_SESSION["changepwd_referer"] ) {101 $_SESSION["changepwd_referer"] = projectUrl();102 }103 104 }105 106 /**107 * @return DsCondition108 */109 protected function getTokenCondition() {110 return DataCondition::FieldEquals( "reset_token", $this->token );111 }112 113 /**114 * @return DsCondition115 */116 protected function getUsernameCondition() {117 if( $this->token ) {118 return $this->getTokenCondition();119 }120 121 $caseInsensitive = Security::caseInsensitiveUsername() ? dsCASE_INSENSITIVE : dsCASE_STRICT;122 return DataCondition::FieldEquals( $this->usernameField, Security::getUserName(), 0, $caseInsensitive );123 }124 125 /**126 * @param String newpass127 * @return 128 */129 protected function getUpdateCommand( $newpass ) {130 $dc = new DsCommand();131 132 if( GetGlobalData( "bEncryptPasswords" ) ) {133 if( !$this->cipherer->isFieldEncrypted( $this->passwordField ) )134 $newpass = Security::hashPassword( $newpass );135 }136 137 $values = array();138 $values[ $this->passwordField ] = $newpass;139 if( $this->token ) {140 $values[ "reset_token" ] = "";141 $values[ "reset_date" ] = NULL;142 if( GetGlobalData( "userRequireActivation" ) ) {143 $values[ GetGlobalData( "userActivationField" ) ] = "1";144 }145 }146 147 $dc->values = $values;148 $dc->filter = $this->getUsernameCondition();149 return $dc;150 }151 152 153 /**154 * @return Array155 */156 protected function getControlValues()157 {158 $filename_values = array();159 $blobfields = array();160 $values = array();161 foreach( $this->changePwdFields as $fName )162 {163 $fControl = $this->getControl( $fName, $this->id );164 $fControl->readWebValue( $values, $blobfields, NULL, NULL, $filename_values );165 }166 167 return $values;168 }169 170 171 /**172 * @return Boolean173 */174 protected function changePassword() {175 // CSRF protection176 if( !isPostRequest() )177 return;178 179 global $globalEvents;180 181 $values = $this->getControlValues();182 183 $dc = new DsCommand();184 $dc->filter = $this->getUsernameCondition();185 $qResult = $this->dataSource->getList( $dc );186 187 $data = $qResult->fetchAssoc();188 $row = $this->cipherer->DecryptFetchedArray( $data );189 190 $dbOldPass = "";191 if( !$row ) {192 $this->message = "Invalid password";193 return false;194 }195 196 $dbOldPass = $row[ $this->passwordField ];197 $username = $row[ $this->usernameField ];198 199 if( !$this->token && $this->pSet->hasOldPassField() ) {200 if( !Security::verifyPassword( $values["oldpass"], $dbOldPass ) ) {201 $this->message = "Invalid password";202 return false;203 }204 }205 206 $oldPass = $dbOldPass;207 208 $newPass = $values["newpass"];209 if( $this->pwdStrong && !checkpassword( $newPass ) ) {210 $this->message = $this->getPwdStrongFailedMessage();211 $this->jsSettings["tableSettings"][ $this->tName ]["msg_passwordError"] = $this->message;212 return false;213 }214 215 $retval = true;216 if( $globalEvents->exists("BeforeChangePassword") )217 $retval = $globalEvents->BeforeChangePassword( $oldPass, $newPass, $this );218 219 $values["newpass"] = $newPass;220 if( $retval ) {221 $dc = $this->getUpdateCommand( $values["newpass"] );222 $this->dataSource->updateSingle( $dc, false );223 224 if( $this->auditObj )225 $this->auditObj->LogChPassword( $username );226 227 if( $globalEvents->exists("AfterChangePassword") )228 $globalEvents->AfterChangePassword( $oldPass, $values["newpass"], $this );229 }230 231 return $retval;232 }233 234 /**235 * @return String236 */237 protected function getPwdStrongFailedMessage()238 {239 $msg = "";240 $pwdLen = GetGlobalData("pwdLen", 0);241 if($pwdLen)242 {243 $fmt = "Password must be at least %% characters length.";244 $fmt = str_replace("%%", "".$pwdLen, $fmt);245 $msg.= "<br>".$fmt;246 }247 $pwdUnique = GetGlobalData("pwdUnique", 0);248 if($pwdUnique)249 {250 $fmt = "Password must contain %% unique characters.";251 $fmt = str_replace("%%", "".$pwdUnique, $fmt);252 $msg.= "<br>".$fmt;253 }254 $pwdDigits = GetGlobalData("pwdDigits", 0);255 if($pwdDigits)256 {257 $fmt = "Password must contain %% digits or symbols.";258 $fmt = str_replace("%%", "".$pwdDigits, $fmt);259 $msg.= "<br>".$fmt;260 }261 if(GetGlobalData("pwdUpperLower", false))262 {263 $fmt = "Password must contain letters in upper and lower case.";264 $msg.= "<br>".$fmt;265 }266 267 if($msg)268 $msg = substr($msg, 4);269 270 return $msg;271 }272 273 /**274 *275 */276 public function process()277 {278 global $globalEvents;279 280 $this->setReferer();281 282 // Before Process event283 if( $globalEvents->exists("BeforeProcessChangePwd") )284 $globalEvents->BeforeProcessChangePwd( $this );285 286 if( $this->action == "Change" ) {287 $this->changedSuccess = $this->changePassword();288 289 if( !$this->changedSuccess && $this->mode == CHANGEPASS_POPUP ) {290 $returnJSON = array();291 $returnJSON['success'] = false;292 293 if( strlen( $this->message ) )294 $returnJSON['message'] = $this->message;295 296 if( !$this->isCaptchaOk )297 $returnJSON['wrongCaptchaFieldName'] = $this->getCaptchaFieldName();298 299 echo printJSON( $returnJSON );300 exit();301 }302 }303 304 if( !$this->changedSuccess ) {305 $this->prepareEditControls();306 } else {307 $this->pageName = $this->pSet->getDefaultPage( $this->successPageType() );308 $this->pSet = new ProjectSettings( $this->tName, $this->successPageType(), $this->pageName, $this->pageTable );309 310 $this->pageData["buttons"] = array_merge( $this->pageData["buttons"], $this->pSet->buttons() );311 foreach( $this->pSet->buttons() as $b ) {312 $this->AddJSFile( "include/button_".$b.".js" );313 }314 }315 316 $this->addCommonJs();317 $this->fillSetCntrlMaps();318 $this->addButtonHandlers();319 $this->doCommonAssignments();320 321 $this->showPage();322 }323 324 /**325 * @param Boolean logged326 */327 protected function reportChangeStatus( $changed )328 {329 $returnJSON = array();330 331 $returnJSON["message"] = $this->message;332 $returnJSON["success"] = true;333 334 echo printJSON( $returnJSON );335 exit();336 } 337 338 /**339 *340 */341 protected function prepareEditControls()342 {343 foreach($this->changePwdFields as $fName)344 {345 $parameters = array();346 $parameters["id"] = $this->id;347 $parameters["mode"] = "add";348 $parameters["field"] = $fName;349 $parameters["format"] = "Password";350 $parameters["pageObj"] = $this;351 $parameters["suggest"] = true;352 $parameters["validate"] = array('basicValidate' => array('IsRequired'));353 354 $parameters["extraParams"] = array();355 $parameters["extraParams"]["getConrirmFieldCtrl"] = true;356 357 $controls = array('controls' => array());358 $controls["controls"]['id'] = $this->id;359 $controls["controls"]['mode'] = "add";360 $controls["controls"]['ctrlInd'] = 0;361 $controls["controls"]['fieldName'] = $fName;362 $controls["controls"]['suggest'] = $parameters["suggest"];363 364 $this->xt->assign_function( $fName."_editcontrol", "xt_buildeditcontrol", $parameters );365 $this->xt->assign($fName."_label", true);366 367 $this->xt->assign("labelfor_" . goodFieldName($fName), "value_".$fName."_".$this->id);368 369 if( $this->is508 )370 $this->xt->assign_section($fName."_label", "<label for=\"value_".$fName."_".$this->id."\">", "</label>");371 372 $this->xt->assign($fName."_block", true);373 374 $this->fillControlsMap($controls);375 }376 }377 378 /**379 *380 */381 protected function assignBody()382 {383 $this->body["begin"] .= GetBaseScriptsForPage(false);384 $this->body["end"] = XTempl::create_method_assignment( "assignBodyEnd", $this );385 386 $this->xt->assignbyref("body", $this->body);387 }388 389 /**390 *391 */392 protected function doCommonAssignments()393 {394 $this->xt->assign("submit_attrs", "id=\"saveButton".$this->id."\"");395 396 if( $this->mode == CHANGEPASS_POPUP ) {397 $this->hideItemType("changepwd_back");398 if( $this->changedSuccess )399 $this->xt->assign("backlink_attrs", "id=\"backButton".$this->id."\"");400 } else {401 $this->xt->assign("backlink_attrs", "href=\"". runner_htmlspecialchars( $_SESSION["changepwd_referer"] )."\"");402 }403 404 $this->xt->assign("message_block", true);405 if( $this->message ) {406 $this->xt->assign("message_class", "alert-danger" );407 $this->xt->assign("message", $this->message);408 } else {409 $this->hideElement("message");410 }411 412 $this->assignBody();413 }414 415 /**416 *417 */418 protected function showPage() {419 global $globalEvents;420 421 if( $this->changedSuccess )422 $this->switchToSuccessPage();423 424 $templatefile = $this->templatefile;425 426 if( $globalEvents->exists("BeforeShowChangePwd") )427 $globalEvents->BeforeShowChangePwd( $this->xt, $templatefile, $this );428 429 if( $this->mode == CHANGEPASS_POPUP )430 {431 $this->xt->assign("footer", false);432 $this->xt->assign("header", false);433 $this->xt->assign("body", $this->body);434 435 $this->displayAJAX( $templatefile, $this->id + 1 );436 exit();437 } 438 439 $this->display( $templatefile );440 }441 442 /**443 * @return String444 */445 public static function readActionFromRequest()446 {447 if( @$_POST["btnSubmit"] )448 return @$_POST["btnSubmit"];449 450 return "";451 }452 453 /**454 * @return Boolean455 */456 protected function checkToken()457 {458 if( !$this->token )459 return true;460 461 $dc = new DsCommand();462 $dc->filter = $this->getTokenCondition();463 $qResult = $this->dataSource->getList( $dc );464 465 $data = $this->cipherer->DecryptFetchedArray( $qResult->fetchAssoc() );466 if( $data )467 return secondsPassedFrom( $data["reset_date"] ) < 86400;468 469 return false;470 }471 472 /**473 * @return Number474 */475 public static function readModeFromRequest()476 {477 if( postvalue("mode") == "popup" )478 return CHANGEPASS_POPUP;479 480 return CHANGEPASS_SIMPLE;481 }482 483 function element2Item( $name ) {484 if( $name == "message" ) {485 return array( "changepwd_message" );486 }487 return parent::element2Item( $name );488 } 489}490?>