JavaScript-based password complexity checker on account creation and password change...
authorMax Semenik <maxsem@users.mediawiki.org>
Thu, 5 Aug 2010 19:16:31 +0000 (19:16 +0000)
committerMax Semenik <maxsem@users.mediawiki.org>
Thu, 5 Aug 2010 19:16:31 +0000 (19:16 +0000)
Note that OutputPage::addPasswordSecurity() doesn't check the enabling setting to make this code reusable by extensions who don't always want to follow core settings.

RELEASE-NOTES
includes/DefaultSettings.php
includes/OutputPage.php
includes/specials/SpecialResetpass.php
includes/specials/SpecialUserlogin.php
includes/templates/Userlogin.php
languages/messages/MessagesEn.php
maintenance/language/messages.inc

index 7fc3fdc..56515d3 100644 (file)
@@ -132,7 +132,8 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
 ** (bug 1211) Subcategories, ordinary pages, and files now page separately.
 ** When several pages are given the same sort key, they sort by their names
    instead of randomly.
-* (bug 23848) Add {{ARTICLEPATH}} Magic Word
+* JavaScript-based password complexity checker on account creation and 
+  password change.
 
 === Bug fixes in 1.17 ===
 * (bug 17560) Half-broken deletion moved image files to deletion archive
index 9ba549e..db553ff 100644 (file)
@@ -1556,7 +1556,7 @@ $wgCacheEpoch = '20030516000000';
  * to ensure that client-side caches do not keep obsolete copies of global
  * styles.
  */
-$wgStyleVersion = '299';
+$wgStyleVersion = '300';
 
 /**
  * This will cache static pages for non-logged-in users to reduce
@@ -5114,6 +5114,11 @@ $wgPoolCounterConf = null;
  */
 $wgUploadMaintenance = false;
 
+/**
+ * Enabes or disables JavaScript-based suggestions of password strength
+ */
+$wgLivePasswordStrengthChecks = true;
 /**
  * For really cool vim folding this needs to be at the end:
  * vim: foldmarker=@{,@} foldmethod=marker
index be9c459..f9825ff 100644 (file)
@@ -1955,6 +1955,22 @@ class OutputPage {
                }
        }
 
+       public function addPasswordSecurity( $passwordId, $retypeId ) {
+               $data = array(
+                       'password' => '#' . $passwordId,
+                       'retype' => '#' . $retypeId,
+                       'messages' => array(),
+               );
+               foreach ( array( 'password-strength', 'password-strength-bad', 'password-strength-mediocre',
+                               'password-strength-acceptable', 'password-strength-good', 'password-retype', 'password-retype-mismatch'
+                       ) as $message ) {
+                       $data['messages'][$message] = wfMsg( $message );
+               }
+               $this->addScript( Html::inlineScript( 'var passwordSecurity=' . FormatJSON::encode( $data ) ) );
+               $this->addScriptFile( 'password.js' );
+               $this->addStyle( 'common/password.css' );
+       }
+
        /** @deprecated */
        public function errorpage( $title, $msg ) {
                wfDeprecated( __METHOD__ );
index 972341e..de832d2 100644 (file)
@@ -106,8 +106,11 @@ class SpecialResetpass extends SpecialPage {
        }
 
        function showForm() {
-               global $wgOut, $wgUser, $wgRequest;
+               global $wgOut, $wgUser, $wgRequest, $wgLivePasswordStrengthChecks;
 
+               if ( $wgLivePasswordStrengthChecks ) {
+                       $wgOut->addPasswordSecurity( 'wpNewPassword', 'wpRetype' );
+               }
                $self = $this->getTitle();
                if ( !$this->mUserName ) {
                        $this->mUserName = $wgUser->getName();
@@ -143,10 +146,10 @@ class SpecialResetpass extends SpecialPage {
                        wfMsgExt( 'resetpass_text', array( 'parse' ) ) . "\n" .
                        Xml::openElement( 'table', array( 'id' => 'mw-resetpass-table' ) ) . "\n" .
                        $this->pretty( array(
-                               array( 'wpName', 'username', 'text', $this->mUserName ),
-                               array( 'wpPassword', $oldpassMsg, 'password', $this->mOldpass ),
-                               array( 'wpNewPassword', 'newpassword', 'password', null ),
-                               array( 'wpRetype', 'retypenew', 'password', null ),
+                               array( 'wpName', 'username', 'text', $this->mUserName, '' ),
+                               array( 'wpPassword', $oldpassMsg, 'password', $this->mOldpass, '' ),
+                               array( 'wpNewPassword', 'newpassword', 'password', null, '<div id="password-strength"></div>' ),
+                               array( 'wpRetype', 'retypenew', 'password', null, '<div id="password-retype"></div>' ),
                        ) ) . "\n" .
                        $rememberMe .
                        "<tr>\n" .
@@ -165,7 +168,7 @@ class SpecialResetpass extends SpecialPage {
        function pretty( $fields ) {
                $out = '';
                foreach ( $fields as $list ) {
-                       list( $name, $label, $type, $value ) = $list;
+                       list( $name, $label, $type, $value, $extra ) = $list;
                        if( $type == 'text' ) {
                                $field = htmlspecialchars( $value );
                        } else {
@@ -186,9 +189,8 @@ class SpecialResetpass extends SpecialPage {
                        else 
                                $out .=  wfMsgHtml( $label );
                        $out .= "</td>\n";
-                       $out .= "\t<td class='mw-input'>";
-                       $out .= $field;
-                       $out .= "</td>\n";
+                       $out .= "\t<td class='mw-input'>$field</td>\n";
+                       $out .= "\t<td>$extra</td>\n";
                        $out .= "</tr>";
                }
                return $out;
index f051110..d8d35dd 100644 (file)
@@ -968,6 +968,10 @@ class LoginForm {
                $titleObj = SpecialPage::getTitleFor( 'Userlogin' );
 
                if ( $this->mType == 'signup' ) {
+                       global $wgLivePasswordStrengthChecks;
+                       if ( $wgLivePasswordStrengthChecks ) {
+                               $wgOut->addPasswordSecurity( 'wpPassword2', 'wpRetype' );
+                       }
                        $template = new UsercreateTemplate();
                        $q = 'action=submitlogin&type=signup';
                        $linkq = 'type=login';
index a36fa2c..7693223 100644 (file)
@@ -169,6 +169,7 @@ class UsercreateTemplate extends QuickTemplate {
                                'autofocus'
                        ) ); ?>
                        </td>
+                       <td></td>
                </tr>
                <tr>
                        <td class="mw-label"><label for='wpPassword2'><?php $this->msg('yourpassword') ?></label></td>
@@ -181,6 +182,7 @@ class UsercreateTemplate extends QuickTemplate {
                                'size' => '20'
                        ) + User::passwordChangeInputAttribs() ); ?>
                        </td>
+                       <td><div id="password-strength"></div></td>
                </tr>
        <?php if( $this->data['usedomain'] ) {
                $doms = "";
@@ -196,6 +198,7 @@ class UsercreateTemplate extends QuickTemplate {
                                        <?php echo $doms ?>
                                </select>
                        </td>
+                       <td></td>
                </tr>
        <?php } ?>
                <tr>
@@ -209,6 +212,7 @@ class UsercreateTemplate extends QuickTemplate {
                        'size' => '20'
                ) + User::passwordChangeInputAttribs() ); ?>
                        </td>
+                       <td><div id="password-retype"></div></td>
                </tr>
                <tr>
                        <?php if( $this->data['useemail'] ) { ?>
@@ -229,12 +233,13 @@ class UsercreateTemplate extends QuickTemplate {
                                                      } ?>
                                        </div>
                                </td>
+                               <td></td>
                        <?php } ?>
                        <?php if( $this->data['userealname'] ) { ?>
                                </tr>
                                <tr>
                                        <td class="mw-label"><label for='wpRealName'><?php $this->msg('yourrealname') ?></label></td>
-                                       <td class="mw-input">
+                                       <td class="mw-input" colspan="2">
                                                <input type='text' class='loginText' name="wpRealName" id="wpRealName"
                                                        tabindex="6"
                                                        value="<?php $this->text('realname') ?>" size='20' />
@@ -242,12 +247,13 @@ class UsercreateTemplate extends QuickTemplate {
                                                        <?php $this->msgWiki('prefs-help-realname'); ?>
                                                </div>
                                        </td>
+                               <td></td>
                        <?php } ?>
                        <?php if( $this->data['usereason'] ) { ?>
                                </tr>
                                <tr>
                                        <td class="mw-label"><label for='wpReason'><?php $this->msg('createaccountreason') ?></label></td>
-                                       <td class="mw-input">
+                                       <td class="mw-input" colspan="2">
                                                <input type='text' class='loginText' name="wpReason" id="wpReason"
                                                        tabindex="7"
                                                        value="<?php $this->text('reason') ?>" size='20' />
@@ -257,7 +263,7 @@ class UsercreateTemplate extends QuickTemplate {
                <?php if( $this->data['canremember'] ) { ?>
                <tr>
                        <td></td>
-                       <td class="mw-input">
+                       <td class="mw-input" colspan="2">
                                <?php
                                global $wgCookieExpiration, $wgLang;
                                echo Xml::checkLabel(
@@ -285,7 +291,7 @@ class UsercreateTemplate extends QuickTemplate {
                                        ?><td><?php
                                }
                        ?></td>
-                       <td class="mw-input">
+                       <td class="mw-input" colspan="2">
                                <input type="<?php echo htmlspecialchars( $inputItem['type'] ) ?>" name="<?php
                                echo htmlspecialchars( $inputItem['name'] ); ?>"
                                        tabindex="<?php echo $tabIndex++; ?>"
@@ -320,7 +326,7 @@ class UsercreateTemplate extends QuickTemplate {
 ?>
                <tr>
                        <td></td>
-                       <td class="mw-submit">
+                       <td class="mw-submit" colspan="2">
                                <input type='submit' name="wpCreateaccount" id="wpCreateaccount"
                                        tabindex="<?php echo $tabIndex++; ?>"
                                        value="<?php $this->msg('createaccount') ?>" />
index 35cabc3..e2f845f 100644 (file)
@@ -1145,6 +1145,13 @@ Please wait before trying again.',
 * Italiano|it
 * Nederlands|nl', # do not translate or duplicate this message to other languages
 'suspicious-userlogout'      => 'Your request to log out was denied because it looks like it was sent by a broken browser or caching proxy.',
+'password-strength'          => 'Estimated password strength: $1',
+'password-strength-bad'      => 'BAD',
+'password-strength-mediocre' => 'mediocre',
+'password-strength-acceptable' => 'acceptable',
+'password-strength-good'     => 'good',
+'password-retype'            => 'Retype password here',
+'password-retype-mismatch'   => 'Passwords don\'t match',
 
 # Password reset dialog
 'resetpass'                 => 'Change password',
index 9754f69..eca9d5c 100644 (file)
@@ -466,6 +466,13 @@ $wgMessageStructure = array(
                'loginlanguagelabel',
                'loginlanguagelinks',
                'suspicious-userlogout',
+               'password-strength',
+               'password-strength-bad',
+               'password-strength-mediocre',
+               'password-strength-acceptable',
+               'password-strength-good',
+               'password-retype',      
+               'password-retype-mismatch',
        ),
        'resetpass' => array(
                'resetpass',