Use local context to get message instead of relying on global variables
[lhc/web/wiklou.git] / includes / specials / SpecialPasswordReset.php
index a400940..b1189ad 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * Implements Special:Blankpage
+ * Implements Special:PasswordReset
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  */
 class SpecialPasswordReset extends FormSpecialPage {
 
+       /**
+        * @var Message
+        */
+       private $email;
+
+       /**
+        * @var Status
+        */
+       private $result;
+
        public function __construct() {
                parent::__construct( 'PasswordReset' );
        }
 
        public function userCanExecute( User $user ) {
-               global $wgPasswordResetRoutes, $wgAuth;
-
-               // Maybe password resets are disabled, or there are no allowable routes
-               if ( !is_array( $wgPasswordResetRoutes ) ||
-                        !in_array( true, array_values( $wgPasswordResetRoutes ) ) ) {
-                       throw new ErrorPageError( 'internalerror', 'passwordreset-disabled' );
-               }
+               return $this->canChangePassword( $user ) === true && parent::userCanExecute( $user );
+       }
 
-               // Maybe the external auth plugin won't allow local password changes
-               if ( !$wgAuth->allowPasswordChange() ) {
+       public function checkExecutePermissions( User $user ) {
+               $error = $this->canChangePassword( $user );
+               if ( is_string( $error ) ) {
+                       throw new ErrorPageError( 'internalerror', $error );
+               } elseif ( !$error ) {
                        throw new ErrorPageError( 'internalerror', 'resetpass_forbidden' );
                }
 
-               // Maybe the user is blocked (check this here rather than relying on the parent
-               // method as we have a more specific error message to use here
-               if ( $user->isBlocked() ) {
-                       throw new ErrorPageError( 'internalerror', 'blocked-mailpassword' );
-               }
-
-               return parent::userCanExecute( $user );
+               return parent::checkExecutePermissions( $user );
        }
 
        protected function getFormFields() {
-               global $wgPasswordResetRoutes;
+               global $wgPasswordResetRoutes, $wgAuth;
                $a = array();
                if ( isset( $wgPasswordResetRoutes['username'] ) && $wgPasswordResetRoutes['username'] ) {
                        $a['Username'] = array(
@@ -72,6 +74,23 @@ class SpecialPasswordReset extends FormSpecialPage {
                        );
                }
 
+               if ( isset( $wgPasswordResetRoutes['domain'] ) && $wgPasswordResetRoutes['domain'] ) {
+                       $domains = $wgAuth->domainList();
+                       $a['Domain'] = array(
+                               'type' => 'select',
+                               'options' => $domains,
+                               'label-message' => 'passwordreset-domain',
+                       );
+               }
+
+               if( $this->getUser()->isAllowed( 'passwordreset' ) ){
+                       $a['Capture'] = array(
+                               'type' => 'check',
+                               'label-message' => 'passwordreset-capture',
+                               'help-message' => 'passwordreset-capture-help',
+                       );
+               }
+
                return $a;
        }
 
@@ -88,6 +107,9 @@ class SpecialPasswordReset extends FormSpecialPage {
                if ( isset( $wgPasswordResetRoutes['email'] ) && $wgPasswordResetRoutes['email'] ) {
                        $i++;
                }
+               if ( isset( $wgPasswordResetRoutes['domain'] ) && $wgPasswordResetRoutes['domain'] ) {
+                       $i++;
+               }
                return wfMessage( 'passwordreset-pretext', $i )->parseAsBlock();
        }
 
@@ -99,6 +121,25 @@ class SpecialPasswordReset extends FormSpecialPage {
         * @return Bool|Array
         */
        public function onSubmit( array $data ) {
+               global $wgAuth;
+
+               if ( isset( $data['Domain'] ) ) {
+                       if ( $wgAuth->validDomain( $data['Domain'] ) ) {
+                               $wgAuth->setDomain( $data['Domain'] );
+                       } else {
+                               $wgAuth->setDomain( 'invaliddomain' );
+                       }
+               }
+
+               if( isset( $data['Capture'] ) && !$this->getUser()->isAllowed( 'passwordreset' ) ){
+                       // The user knows they don't have the passwordreset permission, but they tried to spoof the form.  That's naughty
+                       throw new PermissionsError( 'passwordreset' );
+               }
+
+               /**
+                * @var $firstUser User
+                * @var $users User[]
+                */
 
                if ( isset( $data['Username'] ) && $data['Username'] !== '' ) {
                        $method = 'username';
@@ -164,7 +205,7 @@ class SpecialPasswordReset extends FormSpecialPage {
                        }
                }
 
-               global $wgServer, $wgScript, $wgNewPasswordExpiry;
+               global $wgNewPasswordExpiry;
 
                // All the users will have the same email address
                if ( $firstUser->getEmail() == '' ) {
@@ -174,7 +215,7 @@ class SpecialPasswordReset extends FormSpecialPage {
 
                // We need to have a valid IP address for the hook, but per bug 18347, we should
                // send the user's name if they're logged in.
-               $ip = wfGetIP();
+               $ip = $this->getRequest()->getIP();
                if ( !$ip ) {
                        return array( 'badipaddress' );
                }
@@ -190,64 +231,93 @@ class SpecialPasswordReset extends FormSpecialPage {
                        $password = $user->randomPassword();
                        $user->setNewpassword( $password );
                        $user->saveSettings();
-                       $passwords[] = wfMessage( 'passwordreset-emailelement', $user->getName(), $password );
+                       $passwords[] = wfMessage( 'passwordreset-emailelement', $user->getName(), $password )->plain(); // We'll escape the whole thing later
                }
                $passwordBlock = implode( "\n\n", $passwords );
 
                // Send in the user's language; which should hopefully be the same
                $userLanguage = $firstUser->getOption( 'language' );
 
-               $body = wfMessage( $msg )->inLanguage( $userLanguage );
-               $body->params(
+               $this->email = wfMessage( $msg )->inLanguage( $userLanguage );
+               $this->email->params(
                        $username,
                        $passwordBlock,
                        count( $passwords ),
-                       $wgServer . $wgScript,
+                       Title::newMainPage()->getCanonicalUrl(),
                        round( $wgNewPasswordExpiry / 86400 )
                );
 
                $title = wfMessage( 'passwordreset-emailtitle' );
 
-               $result = $firstUser->sendMail( $title->text(), $body->text() );
+               $this->result = $firstUser->sendMail( $title->escaped(), $this->email->escaped() );
 
-               if ( $result->isGood() ) {
+               // Blank the email if the user is not supposed to see it
+               if( !isset( $data['Capture'] ) || !$data['Capture'] ) {
+                       $this->email = null;
+               }
+
+               if ( $this->result->isGood() ) {
+                       return true;
+               } elseif( isset( $data['Capture'] ) && $data['Capture'] ){
+                       // The email didn't send, but maybe they knew that and that's why they captured it
                        return true;
                } else {
                        // @todo FIXME: The email didn't send, but we have already set the password throttle
                        // timestamp, so they won't be able to try again until it expires...  :(
-                       return array( array( 'mailerror', $result->getMessage() ) );
+                       return array( array( 'mailerror', $this->result->getMessage() ) );
                }
        }
 
        public function onSuccess() {
+               if( $this->getUser()->isAllowed( 'passwordreset' ) && $this->email != null ){
+                       // @todo: Logging
+
+                       if( $this->result->isGood() ){
+                               $this->getOutput()->addWikiMsg( 'passwordreset-emailsent-capture' );
+                       } else {
+                               $this->getOutput()->addWikiMsg( 'passwordreset-emailerror-capture', $this->result->getMessage() );
+                       }
+
+                       $this->getOutput()->addHTML( Html::rawElement( 'pre', array(), $this->email->escaped() ) );
+               }
+
                $this->getOutput()->addWikiMsg( 'passwordreset-emailsent' );
                $this->getOutput()->returnToMain();
        }
 
-       /**
-        * Hide the password reset page if resets are disabled.
-        * @return Bool
-        */
-       function isListed() {
+       protected function canChangePassword( User $user ) {
                global $wgPasswordResetRoutes, $wgAuth;
 
                // Maybe password resets are disabled, or there are no allowable routes
                if ( !is_array( $wgPasswordResetRoutes ) ||
-                        !in_array( true, array_values( $wgPasswordResetRoutes ) ) ) {
-                       return false;
+                        !in_array( true, array_values( $wgPasswordResetRoutes ) ) )
+               {
+                       return 'passwordreset-disabled';
                }
 
                // Maybe the external auth plugin won't allow local password changes
                if ( !$wgAuth->allowPasswordChange() ) {
-                       return false;
+                       return 'resetpass_forbidden';
                }
 
                // Maybe the user is blocked (check this here rather than relying on the parent
                // method as we have a more specific error message to use here
                if ( $user->isBlocked() ) {
-                       return false;
+                       return 'blocked-mailpassword';
+               }
+
+               return true;
+       }
+
+       /**
+        * Hide the password reset page if resets are disabled.
+        * @return Bool
+        */
+       function isListed() {
+               if ( $this->canChangePassword( $this->getUser() ) === true ) {
+                       return parent::isListed();
                }
 
-               return parent::isListed();
+               return false;
        }
-}
\ No newline at end of file
+}