WordPress.org

Make WordPress Core

Ticket #4470: password-strength-meter-revised.diff

File password-strength-meter-revised.diff, 17.9 KB (added by JDTrower, 10 years ago)

New password strength function and PHP function (per #5404).

  • wp-admin/includes/user.php

     
    102102        if ( $pass1 != $pass2 )
    103103                $errors->add( 'pass', __( '<strong>ERROR</strong>: Please enter the same password in the two password fields.' ), array( 'form-field' => 'pass1' ) );
    104104
     105        /* Check password strength */
     106        if ( get_option("strong_passwords") == 1 && wp_test_password($pass1) != "") $errors->add( 'pass', __('<strong>ERROR</strong>: ') .wp_test_password($pass1), array( 'form-field' => 'pass1' ) );
     107               
    105108        if (!empty ( $pass1 ))
    106109                $user->user_pass = $pass1;
    107110
  • wp-admin/js/password-strength-meter.js

     
    1 // Password strength meter
    2 // This jQuery plugin is written by firas kassem [2007.04.05]
    3 // Firas Kassem  phiras.wordpress.com || phiras at gmail {dot} com
    4 // for more information : http://phiras.wordpress.com/2007/04/08/password-strength-meter-a-jquery-plugin/
    5 
    6 var shortPass = 'Too short'
    7 var badPass = 'Bad'
    8 var goodPass = 'Good'
    9 var strongPass = 'Strong'
    10 
    11 
    12 
    13 function passwordStrength(password,username)
     1function passwordStrength(password)
    142{
    15     score = 0
    16    
    17     //password < 4
    18     if (password.length < 4 ) { return shortPass }
    19    
    20     //password == username
    21     if (password.toLowerCase()==username.toLowerCase()) return badPass
    22    
    23     //password length
    24     score += password.length * 4
    25     score += ( checkRepetition(1,password).length - password.length ) * 1
    26     score += ( checkRepetition(2,password).length - password.length ) * 1
    27     score += ( checkRepetition(3,password).length - password.length ) * 1
    28     score += ( checkRepetition(4,password).length - password.length ) * 1
     3        var desc = new Array();
     4        desc[0] = "Too Short";
     5        desc[1] = "Very Weak";
     6        desc[2] = "Weak";
     7        desc[3] = "Medium";
     8        desc[4] = "Better";
     9        desc[5] = "Strong";
     10        desc[6] = "Very Strong";
    2911
    30     //password has 3 numbers
    31     if (password.match(/(.*[0-9].*[0-9].*[0-9])/))  score += 5
    32    
    33     //password has 2 sybols
    34     if (password.match(/(.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~])/)) score += 5
    35    
    36     //password has Upper and Lower chars
    37     if (password.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/))  score += 10
    38    
    39     //password has number and chars
    40     if (password.match(/([a-zA-Z])/) && password.match(/([0-9])/))  score += 15
    41     //
    42     //password has number and symbol
    43     if (password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([0-9])/))  score += 15
    44    
    45     //password has char and symbol
    46     if (password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([a-zA-Z])/))  score += 15
    47    
    48     //password is just a nubers or chars
    49     if (password.match(/^\w+$/) || password.match(/^\d+$/) )  score -= 10
    50    
    51     //verifing 0 < score < 100
    52     if ( score < 0 )  score = 0
    53     if ( score > 100 )  score = 100
    54    
    55     if (score < 34 )  return badPass
    56     if (score < 68 )  return goodPass
    57     return strongPass
    58 }
     12        var strength = 100;
     13        var score        = 0;
     14               
     15        if ( password.length <= 7 )
     16                strength -= ( password.length * 5 );
     17       
     18        if ( password.length > 7 )
     19                strength -= ( ( password.length * 10 ) - ( 7 * 5 ) );
     20       
     21        var characters = "";
     22        var nNumbers = 0;
     23        var nLowercase = 0;
     24        var nUppercase = 0;
     25        var nSymbols = 0;
     26       
     27        for ( i = 0; i < password.length; i++ )
     28        {
     29                characters = password.charAt(i);
     30                if ( characters >= "0" && characters <= "9" ) nNumbers++;
     31                else if ( characters >= "a" && characters <= "z" ) nLowercase++;
     32                else if ( characters >= "A" && characters <= "Z" ) nUppercase++;
     33                else nSymbols++;
     34        }
     35       
     36        if ( nLowercase > 0 )
     37                strength -= ( nLowercase * 1 );
     38       
     39        if ( nUppercase >= 1 )
     40                strength -= ( nUppercase * 3 );
     41       
     42        if ( nNumbers >= 1 )
     43                strength -= ( nNumbers * 7 );
     44       
     45        if ( nSymbols >= 1 )
     46                strength -= ( nSymbols * 10 );
     47       
     48        //verifing 0 < strength < 100
     49        if ( strength < 0 ) strength = 0;
     50        if ( strength > 100 ) strength = 100;
    5951
     52        var lca = password.match(/[a-z]/);
     53        var uca = password.match(/[A-Z]/);
     54        var nmb = password.match(/[0-9]/);
     55        var smb = password.match(/[~,!,@,#,$,%,^,&,*,(,),\-,_,\=,\+,\[,\],\{,\},\;,\:,\,,\.,\/,\<,\>,?,\|,\\,\',\",\`]/)
    6056
    61 // checkRepetition(1,'aaaaaaabcbc')   = 'abcbc'
    62 // checkRepetition(2,'aaaaaaabcbc')   = 'aabc'
    63 // checkRepetition(2,'aaaaaaabcdbcd') = 'aabcd'
    64 
    65 function checkRepetition(pLen,str) {
    66     res = ""
    67     for ( i=0; i<str.length ; i++ ) {
    68         repeated=true
    69         for (j=0;j < pLen && (j+i+pLen) < str.length;j++)
    70             repeated=repeated && (str.charAt(j+i)==str.charAt(j+i+pLen))
    71         if (j<pLen) repeated=false
    72         if (repeated) {
    73             i+=pLen-1
    74             repeated=false
    75         }
    76         else {
    77             res+=str.charAt(i)
    78         }
    79     }
    80     return res
    81 }
    82 // Password strength meter
    83 // This jQuery plugin is written by firas kassem [2007.04.05]
    84 // Firas Kassem  phiras.wordpress.com || phiras at gmail {dot} com
    85 // for more information : http://phiras.wordpress.com/2007/04/08/password-strength-meter-a-jquery-plugin/
    86 
    87 var shortPass = 'Too short'
    88 var badPass = 'Bad'
    89 var goodPass = 'Good'
    90 var strongPass = 'Strong'
    91 
    92 
    93 
    94 function passwordStrength(password,username)
    95 {
    96     score = 0
    97    
    98     //password < 4
    99     if (password.length < 4 ) { return shortPass }
    100    
    101     //password == username
    102     if (password.toLowerCase()==username.toLowerCase()) return badPass
    103    
    104     //password length
    105     score += password.length * 4
    106     score += ( checkRepetition(1,password).length - password.length ) * 1
    107     score += ( checkRepetition(2,password).length - password.length ) * 1
    108     score += ( checkRepetition(3,password).length - password.length ) * 1
    109     score += ( checkRepetition(4,password).length - password.length ) * 1
    110 
    111     //password has 3 numbers
    112     if (password.match(/(.*[0-9].*[0-9].*[0-9])/))  score += 5
    113    
    114     //password has 2 sybols
    115     if (password.match(/(.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~])/)) score += 5
    116    
    117     //password has Upper and Lower chars
    118     if (password.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/))  score += 10
    119    
    120     //password has number and chars
    121     if (password.match(/([a-zA-Z])/) && password.match(/([0-9])/))  score += 15
    122     //
    123     //password has number and symbol
    124     if (password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([0-9])/))  score += 15
    125    
    126     //password has char and symbol
    127     if (password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([a-zA-Z])/))  score += 15
    128    
    129     //password is just a nubers or chars
    130     if (password.match(/^\w+$/) || password.match(/^\d+$/) )  score -= 10
    131    
    132     //verifing 0 < score < 100
    133     if ( score < 0 )  score = 0
    134     if ( score > 100 )  score = 100
    135    
    136     if (score < 34 )  return badPass
    137     if (score < 68 )  return goodPass
    138     return strongPass
    139 }
    140 
    141 
    142 // checkRepetition(1,'aaaaaaabcbc')   = 'abcbc'
    143 // checkRepetition(2,'aaaaaaabcbc')   = 'aabc'
    144 // checkRepetition(2,'aaaaaaabcdbcd') = 'aabcd'
    145 
    146 function checkRepetition(pLen,str) {
    147     res = ""
    148     for ( i=0; i<str.length ; i++ ) {
    149         repeated=true
    150         for (j=0;j < pLen && (j+i+pLen) < str.length;j++)
    151             repeated=repeated && (str.charAt(j+i)==str.charAt(j+i+pLen))
    152         if (j<pLen) repeated=false
    153         if (repeated) {
    154             i+=pLen-1
    155             repeated=false
    156         }
    157         else {
    158             res+=str.charAt(i)
    159         }
    160     }
    161     return res
    162 }
     57        if ( ( strength <= 100 ) && ( ( lca ) || ( uca ) || ( nmb ) || ( smb ) ) ) score ++;
     58        if ( ( strength <= 58 ) && ( ( ( lca ) && ( uca ) ) || ( ( lca ) && ( nmb ) ) || ( ( lca ) && ( smb ) ) || ( ( uca ) && ( nmb ) ) || ( ( uca ) && ( smb ) ) || ( ( nmb ) && ( smb ) ) ) ) score++;
     59        if ( ( strength <= 54 ) && ( ( ( lca ) && ( uca ) && ( nmb ) ) || ( ( lca ) && ( uca ) && ( smb ) ) || ( ( lca ) && ( nmb ) && ( smb ) ) || ( ( uca ) && ( nmb ) && ( smb ) ) ) ) score++;
     60        if ( ( strength <= 48 ) && ( password.length >= 7 ) && ( ( ( lca ) && ( uca ) && ( nmb ) ) || ( ( lca ) && ( uca ) && ( smb ) ) || ( ( lca ) && ( nmb ) && ( smb ) ) || ( ( uca ) && ( nmb ) && ( smb ) ) ) ) score++;
     61        if ( ( strength <= 35 ) && ( password.length >= 7 ) && ( lca ) && ( uca ) && ( nmb ) && ( smb ) ) score++;
     62        if ( ( strength <= 24 ) && ( password.length >= 12 ) && ( lca ) && ( uca ) && ( nmb ) && ( smb ) ) score++;
     63       
     64        if ( ( password.length > 0 ) && ( score <= 3 ) )
     65                document.getElementById("submit").disabled = true;
     66        else
     67                document.getElementById("submit").disabled = false;
     68       
     69        document.getElementById("passwordDescription").innerHTML = desc[score];
     70        document.getElementById("passwordStrength").className = "strength" + score;
     71}
     72 No newline at end of file
  • wp-admin/options-general.php

     
    5454<select name="default_role" id="default_role"><?php wp_dropdown_roles( get_option('default_role') ); ?></select></label>
    5555</td>
    5656</tr>
     57<tr valign="top">
     58<th scope="row"><?php _e('Security:') ?></th>
     59<td><label for="strong_passwords">
     60<input name="strong_passwords" type="checkbox" id="strong_passwords" value="1" <?php checked('1', get_option('strong_passwords')); ?> />
     61<?php _e('Enforce Strong Passwords') ?></label>
     62</td>
    5763<tr>
    5864<th scope="row"><?php _e('<abbr title="Coordinated Universal Time">UTC</abbr> time is:') ?> </th>
    5965<td><code><?php echo gmdate(__('Y-m-d g:i:s a')); ?></code></td>
     
    9298
    9399<p class="submit"><input type="submit" name="Submit" value="<?php _e('Update Options &raquo;') ?>" />
    94100<input type="hidden" name="action" value="update" />
    95 <input type="hidden" name="page_options" value="<?php if ( ! defined( 'WP_SITEURL' ) ) echo 'siteurl,'; if ( ! defined( 'WP_HOME' ) ) echo 'home,'; ?>blogname,blogdescription,admin_email,users_can_register,gmt_offset,date_format,time_format,start_of_week,comment_registration,default_role" />
     101<input type="hidden" name="page_options" value="<?php if ( ! defined( 'WP_SITEURL' ) ) echo 'siteurl,'; if ( ! defined( 'WP_HOME' ) ) echo 'home,'; ?>blogname,blogdescription,admin_email,users_can_register,gmt_offset,date_format,time_format,start_of_week,comment_registration,default_role,strong_passwords" />
    96102</p>
    97103</form>
    98104
  • wp-admin/profile.php

     
    33
    44function profile_js ( ) {
    55?>
    6 <script type="text/javascript">
    7         function check_pass_strength ( ) {
     6<script type="text/javascript"> 
     7        function check_pass_strength ( ) { 
    88
    9                 var pass = jQuery('#pass1').val();
    10                 var user = jQuery('#user_login').val();
     9                var pass = jQuery('#pass1').val(); 
     10                var user = jQuery('#user_login').val(); 
    1111
    12                 // get the result as an object, i'm tired of typing it
    13                 var res = jQuery('#pass-strength-result');
     12                // get the result as an object, i'm tired of typing it 
     13                var res = jQuery('#pass-strength-result'); 
    1414
    1515                var strength = passwordStrength(pass, user);
    1616
    17                 jQuery(res).removeClass('short bad good strong');
     17        jQuery(res).removeClass('short vweak weak medium better strong vstrong');
     18               
     19                if ( strength == 'Very Weak' ) {
     20                        jQuery(res).addClass('vweak');
     21                        jQuery(res).html( pwsL10n.vweak );
     22                }
     23                else if ( strength == 'Weak' ) {
     24                        jQuery(res).addClass('weak');
     25                        jQuery(res).html( pwsL10n.weak );
     26                }
     27                else if ( strength == 'Medium' ) {
     28                        jQuery(res).addClass('medium');
     29                        jQuery(res).html( pwsL10n.medium );
     30                }
     31                else if ( strength == 'Better' ) {
     32                        jQuery(res).addClass('better');
     33                        jQuery(res).html( pwsL10n.better );
     34                }
     35                else if ( strength == 'Strong' ) {
     36                        jQuery(res).addClass('strong');
     37                        jQuery(res).html( pwsL10n.strong );
     38                }
     39                else if ( strength == 'Very Strong' ) {
     40                        jQuery(res).addClass('vstrong');
     41                        jQuery(res).html( pwsL10n.vstrong );
     42                }
     43                else {
     44                        // this catches 'Too short' and the off chance anything else comes along
     45                        jQuery(res).addClass('short');
     46                        jQuery(res).html( pwsL10n.short );
     47                }
    1848
    19                 if ( strength == 'Bad' ) {
    20                         jQuery(res).addClass('bad');
    21                         jQuery(res).html( pwsL10n.bad );
    22                 }
    23                 else if ( strength == 'Good' ) {
    24                         jQuery(res).addClass('good');
    25                         jQuery(res).html( pwsL10n.good );
    26                 }
    27                 else if ( strength == 'Strong' ) {
    28                         jQuery(res).addClass('strong');
    29                         jQuery(res).html( pwsL10n.strong );
    30                 }
    31                 else {
    32                         // this catches 'Too short' and the off chance anything else comes along
    33                         jQuery(res).addClass('short');
    34                         jQuery(res).html( pwsL10n.short );
    35                 }
     49        }
    3650
    37         }
    38 
    39         jQuery(document).ready( function() { jQuery('#pass1').keyup( check_pass_strength ) } );
     51jQuery(document).ready( function() { jQuery('#pass1').keyup( check_pass_strength ) } );
    4052</script>
    4153<?php
    4254}
     
    160172<input type="password" name="pass2" id="pass2" size="16" value="" />
    161173</label></p>
    162174<p><strong><?php _e('Password Strength:'); ?></strong></p>
    163 <div id="pass-strength-result"><?php _e('Too short'); ?></div>
    164 <p><?php _e('Hint: Use upper and lower case characters, numbers and symbols like !"?$%^&( in your password.'); ?></p>
     175<p><div id="passwordDescription">Password not entered</div>
     176<div id="passwordStrength" class="strength0"></div></p>
     177<p><?php _e('Hint: You must use upper and lower case characters as well as numbers and/or symbols in your password with a minimum password length of 7 characters.'); ?></p>
     178<p><?php _e('You <strong>MUST</strong> have a strength of "Better," "Strong," or "Very Strong" to change your password.'); ?></p>
    165179</fieldset>
    166180<?php endif; ?>
    167181
     
    190204    endif;
    191205    ?>
    192206  </table>
    193 <p class="submit"><input type="submit" value="<?php _e('Update Profile &raquo;') ?>" name="submit" /></p>
     207<p class="submit"><input type="submit" value="<?php _e('Update Profile &raquo;') ?>" name="submit" id="submit" /></p>
    194208</form>
    195209
    196210</div>
  • wp-admin/wp-admin.css

     
    820820        color: #036;
    821821}
    822822
    823 #pass-strength-result {
    824         padding: 3px 5px 3px 5px;
    825         margin-top: 3px;
    826         text-align: center;
    827         background-color: #e3e3e3;
    828         border: 1px solid #000000;
     823#passwordStrength {
     824        height:10px;
     825        display:block;
     826        float:left;
    829827}
    830828
    831 #pass-strength-result.short {
    832         background-color: #e3e3e3;
    833         border: 1px solid #000000;
     829.strength0 {
     830        width:102%;
     831        background:#cccccc;
    834832}
    835833
    836 #pass-strength-result.bad {
    837         background-color: #ffeff7;
    838         border: 1px solid #cc6699;
     834.strength1 {
     835        width:17%;
     836        background:#ff0000;
    839837}
    840838
    841 #pass-strength-result.good {
    842         background-color: #effff4;
    843         border: 1px solid #66cc87;
     839.strength2 {
     840        width:34%;     
     841        background:#ff5f5f;
    844842}
    845843
    846 #pass-strength-result.strong {
    847         background-color: #59ef86;
    848         border: 1px solid #319f52;
     844.strength3 {
     845        width:51%;
     846        background:#ffff66;
    849847}
    850848
     849.strength4 {
     850        width:68%;
     851        background:#aefe36;
     852}
     853
     854.strength5 {
     855        background:#4dcd00;
     856        width:85%;
     857}
     858
     859.strength6 {
     860        background:#308000;
     861        width:102%;
     862}
     863
    851864a.view-comment-post-link {
    852865        position: absolute;
    853866        text-decoration:underline;
  • wp-includes/pluggable.php

     
    707707}
    708708endif;
    709709
     710if ( !function_exists('wp_test_password') ) :
     711function wp_test_password($password) {
     712        $error = "";
     713       
     714        // Check that the password containes lowercase and uppercase letters, numbers, and symbols
     715        $lowercase = false;
     716        $uppercase = false;
     717        $numbers   = false;
     718        $symbols   = false;
     719        for($i=0;$i<strlen($password) && !($lowercase && $uppercase && $numbers && $symbols);$i++){
     720                $lowercase = $lowercase || (ord(substr($password,$i,1)) > 96 && ord(substr($password,$i,1)) < 123);
     721                $uppercase = $uppercase || (ord(substr($password,$i,1)) > 64 && ord(substr($password,$i,1)) < 91);
     722                $numbers   = $numbers || (ord(substr($password,$i,1)) > 47 && ord(substr($password,$i,1)) < 58);
     723                $symbols   = $symbols || ((ord(substr($password,$i,1)) > 32 && ord(substr($password,$i,1)) < 48) || (ord(substr($password,$i,1)) > 57 && ord(substr($password,$i,1)) < 65) || (ord(substr($password,$i,1)) > 90 && ord(substr($password,$i,1)) < 97) || (ord(substr($password,$i,1)) > 122 && ord(substr($password,$i,1)) < 127));
     724        }
     725       
     726        if (!($lowercase)) $error .= __("The password does not contain lowercase letters<br/>\n");
     727        if (!($uppercase)) $error .= __("The password does not contain uppercase letters<br/>\n");
     728        if (!($numbers || $symbols)) $error .= __("The password does not contain numbers and/or symbols<br/>\n");
     729        // if (!($symbols)) $error .= __("The password does not contain symbols<br/>\n");
     730       
     731        // Check password length
     732        if(strlen($password) < 7) $error .= __("The password is not long enough<br/>\n");
     733        return $error;
     734}
     735endif;
     736
    710737if ( !function_exists('wp_salt') ) :
    711738function wp_salt() {
    712739
  • wp-includes/script-loader.php

     
    108108                        $this->add( 'password-strength-meter', '/wp-admin/js/password-strength-meter.js', array('jquery'), '20070405' );
    109109                        $this->localize( 'password-strength-meter', 'pwsL10n', array(
    110110                                'short' => __('Too short'),
    111                                 'bad' => __('Bad'),
    112                                 'good' => __('Good'),
    113                                 'strong' => __('Strong')
     111                                'vweak' => __('Very Weak'),
     112                                'weak' => __('Weak'),
     113                                'medium' => __('Medium'),
     114                                'better' => __('Better'),
     115                                'strong' => __('Strong'),
     116                                'vstrong' => __('Very Strong')
    114117                        ) );
    115118                        $this->add( 'admin-comments', '/wp-admin/js/edit-comments.js', array('wp-lists'), '20071104' );
    116119                        $this->add( 'admin-posts', '/wp-admin/js/edit-posts.js', array('wp-lists'), '20071023' );