WordPress.org

Make WordPress Core

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

File password-strength-meter-revised.diff, 17.9 KB (added by JDTrower, 8 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' );