/**
  * Adds an user to the database
  * @param String $sUsername user name
  * @param String $sPassword password
  * @param String $sRePassword password confirmation
  * @param String $sEmail user's e-mail address
  * @param String $sRealname user's real name
  * @param Array $aGroups user name
  * @return string json encoded response
  */
 public static function editUser($sUsername, $sPassword, $sRePassword, $sEmail, $sRealname, $aGroups = array())
 {
     $res = $resDelGroups = $resInsGroups = $resERealUser = false;
     if (wfReadOnly()) {
         global $wgReadOnly;
         return FormatJson::encode(array('success' => false, 'message' => array(wfMessage('bs-readonly', $wgReadOnly)->plain())));
     }
     if (BsCore::checkAccessAdmission('wikiadmin') === false) {
         return true;
     }
     $aAnswer = array('success' => true, 'errors' => array(), 'message' => array());
     $oUser = User::newFromName($sUsername);
     if ($oUser->getId() === 0) {
         $aAnswer['success'] = false;
         $aAnswer['message'][] = wfMessage('bs-usermanager-idnotexist')->plain();
         // id_noexist = 'This user ID does not exist'
     }
     if (!empty($sPassword) && !$oUser->isValidPassword($sPassword)) {
         $aAnswer['success'] = false;
         $aAnswer['errors'][] = array('id' => 'pass', 'message' => wfMessage('bs-usermanager-invalid-pwd')->plain());
     }
     if ($sPassword !== $sRePassword) {
         $aAnswer['success'] = false;
         $aAnswer['errors'][] = array('id' => 'newpass', 'message' => wfMessage('badretype')->plain());
     }
     if (strpos($sRealname, '\\')) {
         $aAnswer['success'] = false;
         $aAnswer['errors'][] = array('id' => 'realname', 'message' => wfMessage('bs-usermanager-invalid-realname')->plain());
     }
     if ($sEmail != '' && Sanitizer::validateEmail($sEmail) === false) {
         $aAnswer['success'] = false;
         $aAnswer['errors'][] = array('id' => 'email', 'message' => wfMessage('bs-usermanager-invalid-email-gen')->plain());
     }
     global $wgUser;
     if ($wgUser->getId() == $oUser->getId() && in_array('sysop', $wgUser->getEffectiveGroups()) && !in_array('sysop', $aGroups)) {
         $aAnswer['success'] = false;
         $aAnswer['errors'][] = array('id' => 'groups', 'message' => wfMessage('bs-usermanager-no-self-desysop')->plain());
     }
     $dbw = wfGetDB(DB_MASTER);
     if ($aAnswer['success']) {
         if (!empty($sPassword)) {
             $res = $dbw->update('user', array('user_password' => User::crypt($sPassword)), array('user_id' => $oUser->getId()));
         } else {
             $res = true;
         }
         $resDelGroups = $dbw->delete('user_groups', array('ug_user' => $oUser->getId()));
         $resInsGroups = true;
         if (is_array($aGroups)) {
             foreach ($aGroups as $sGroup) {
                 if (in_array($sGroup, self::$excludegroups)) {
                     continue;
                 }
                 $resInsGroups = $dbw->insert('user_groups', array('ug_user' => $oUser->getId(), 'ug_group' => addslashes($sGroup)));
             }
         }
         $resERealUser = $dbw->update('user', array('user_real_name' => $sRealname, 'user_email' => $sEmail), array('user_id' => $oUser->getId()));
         $oUser->invalidateCache();
     }
     if ($res === false || $resDelGroups === false || !$resInsGroups || $resERealUser === false) {
         $aAnswer['success'] = false;
         $aAnswer['message'][] = wfMessage('bs-usermanager-db-error')->plain();
     }
     if ($aAnswer['success']) {
         $aAnswer['message'][] = wfMessage('bs-usermanager-save-successful')->plain();
     }
     return FormatJson::encode($aAnswer);
 }
 protected function acceptRequest(IContextSource $context)
 {
     global $wgAuth, $wgAccountRequestTypes, $wgConfirmAccountSaveInfo;
     global $wgAllowAccountRequestFiles, $wgConfirmAccountFSRepos;
     $accReq = $this->accountReq;
     // convenience
     # Now create user and check if the name is valid
     $user = User::newFromName($this->userName, 'creatable');
     if (!$user) {
         return array('accountconf_invalid_name', wfMsgHtml('noname'));
     }
     # Check if account name is already in use
     if (0 != $user->idForName() || $wgAuth->userExists($user->getName())) {
         return array('accountconf_user_exists', wfMsgHtml('userexists'));
     }
     $dbw = wfGetDB(DB_MASTER);
     $dbw->begin();
     # Make a random password
     $p = User::randomPassword();
     # Insert the new user into the DB...
     $tokenExpires = $accReq->getEmailTokenExpires();
     $authenticated = $accReq->getEmailAuthTimestamp();
     $params = array('real_name' => $accReq->getRealName(), 'newpassword' => User::crypt($p), 'email' => $accReq->getEmail(), 'email_authenticated' => $dbw->timestampOrNull($authenticated), 'email_token_expires' => $dbw->timestamp($tokenExpires), 'email_token' => $accReq->getEmailToken());
     $user = User::createNew($user->getName(), $params);
     # Grant any necessary rights (exclude blank or dummy groups)
     $group = self::getGroupFromType($this->type);
     if ($group != '' && $group != 'user' && $group != '*') {
         $user->addGroup($group);
     }
     $acd_id = null;
     // used for rollback cleanup
     # Save account request data to credentials system
     if ($wgConfirmAccountSaveInfo) {
         $key = $accReq->getFileStorageKey();
         # Copy any attached files to new storage group
         if ($wgAllowAccountRequestFiles && $key) {
             $repoOld = new FSRepo($wgConfirmAccountFSRepos['accountreqs']);
             $repoNew = new FSRepo($wgConfirmAccountFSRepos['accountcreds']);
             $pathRel = UserAccountRequest::relPathFromKey($key);
             $oldPath = $repoOld->getZonePath('public') . '/' . $pathRel;
             $triplet = array($oldPath, 'public', $pathRel);
             $status = $repoNew->storeBatch(array($triplet));
             // copy!
             if (!$status->isOK()) {
                 $dbw->rollback();
                 # DELETE new rows in case there was a COMMIT somewhere
                 $this->acceptRequest_rollback($dbw, $user->getId(), $acd_id);
                 return array('accountconf_copyfailed', $context->getOutput()->parse($status->getWikiText()));
             }
         }
         $acd_id = $dbw->nextSequenceValue('account_credentials_acd_id_seq');
         # Move request data into a separate table
         $dbw->insert('account_credentials', array('acd_user_id' => $user->getID(), 'acd_real_name' => $accReq->getRealName(), 'acd_email' => $accReq->getEmail(), 'acd_email_authenticated' => $dbw->timestampOrNull($authenticated), 'acd_bio' => $accReq->getBio(), 'acd_notes' => $accReq->getNotes(), 'acd_urls' => $accReq->getUrls(), 'acd_ip' => $accReq->getIP(), 'acd_filename' => $accReq->getFileName(), 'acd_storage_key' => $accReq->getFileStorageKey(), 'acd_areas' => $accReq->getAreas('flat'), 'acd_registration' => $dbw->timestamp($accReq->getRegistration()), 'acd_accepted' => $dbw->timestamp(), 'acd_user' => $this->admin->getID(), 'acd_comment' => $this->reason, 'acd_id' => $acd_id), __METHOD__);
         if (is_null($acd_id)) {
             $acd_id = $dbw->insertId();
             // set $acd_id to ID inserted
         }
     }
     # Add to global user login system (if there is one)
     if (!$wgAuth->addUser($user, $p, $accReq->getEmail(), $accReq->getRealName())) {
         $dbw->rollback();
         # DELETE new rows in case there was a COMMIT somewhere
         $this->acceptRequest_rollback($dbw, $user->getId(), $acd_id);
         return array('accountconf_externaldberror', wfMsgHtml('externaldberror'));
     }
     # OK, now remove the request from the queue
     $accReq->remove();
     # Commit this if we make past the CentralAuth system
     # and the groups are added. Next step is sending out an
     # email, which we cannot take back...
     $dbw->commit();
     # Prepare a temporary password email...
     if ($this->reason != '') {
         $msg = "confirmaccount-email-body2-pos{$this->type}";
         # If the user is in a group and there is a welcome for that group, use it
         if ($group && !wfEmptyMsg($msg)) {
             $ebody = wfMsgExt($msg, array('parsemag', 'content'), $user->getName(), $p, $this->reason);
             # Use standard if none found...
         } else {
             $ebody = wfMsgExt('confirmaccount-email-body2', array('parsemag', 'content'), $user->getName(), $p, $this->reason);
         }
     } else {
         $msg = "confirmaccount-email-body-pos{$this->type}";
         # If the user is in a group and there is a welcome for that group, use it
         if ($group && !wfEmptyMsg($msg)) {
             $ebody = wfMsgExt($msg, array('parsemag', 'content'), $user->getName(), $p, $this->reason);
             # Use standard if none found...
         } else {
             $ebody = wfMsgExt('confirmaccount-email-body', array('parsemag', 'content'), $user->getName(), $p, $this->reason);
         }
     }
     # Actually send out the email (@TODO: rollback on failure including $wgAuth)
     $result = $user->sendMail(wfMsgForContent('confirmaccount-email-subj'), $ebody);
     /*
     if ( !$result->isOk() ) {
     	# DELETE new rows in case there was a COMMIT somewhere
     	$this->acceptRequest_rollback( $dbw, $user->getId(), $acd_id );
     	return array( 'accountconf_mailerror',
     		wfMsg( 'mailerror', $context->getOutput()->parse( $result->getWikiText() ) ) );
     }
     */
     # Update user count
     $ssUpdate = new SiteStatsUpdate(0, 0, 0, 0, 1);
     $ssUpdate->doUpdate();
     # Safe to hook/log now...
     wfRunHooks('AddNewAccount', array($user, false));
     $user->addNewUserLogEntry();
     # Clear cache for notice of how many account requests there are
     ConfirmAccount::clearAccountRequestCountCache();
     # Delete any attached file and don't stop the whole process if this fails
     if ($wgAllowAccountRequestFiles) {
         $key = $accReq->getFileStorageKey();
         if ($key) {
             $repoOld = new FSRepo($wgConfirmAccountFSRepos['accountreqs']);
             $pathRel = UserAccountRequest::relPathFromKey($key);
             $oldPath = $repoOld->getZonePath('public') . '/' . $pathRel;
             if (file_exists($oldPath)) {
                 unlink($oldPath);
                 // delete!
             }
         }
     }
     # Start up the user's userpages if set to do so.
     # Will not append, so previous content will be blanked.
     $this->createUserPage($user);
     # Greet the new user if set to do so.
     $this->createUserTalkPage($user);
     return array(true, null);
 }
 /**
  * Salt and hash a new plaintext password.
  * @param string $password plaintext
  * @return array of strings, salt and hash
  */
 protected function saltedPassword($password)
 {
     return array('', User::crypt($password));
 }