Drupal 5: Add a password strength meter to the user edit form using Google API

Here is the code I used to add a password strength meter to the user edit form. First, I added a menu item that will be used by AJAX to process the user’s password. The path will be used like this: http://MYWEBSITE/passwordStrength/USERPASSWORD. As you can see in the callback arguments, the remainder of the query string after the first “/” is passed into the callback function.

Drupal hook_menu:

<?php
function MYMODULE_menu() {
  $items = array();
  // ...code...
  $items[] = array(
    'path' => 'passwordStrength',
    'callback' => 'MYMODULE_passwordStrength',
    'type' => MENU_CALLBACK,
    'access' => TRUE,
    'callback arguments' => array(array_pop(explode("/",$_REQUEST['q'],2))),
  );
  // ...code...
  return $items;
}
?>

Here’s the callback function. It returns an integer to the screen with no theming.

<?php
function patient_portal_callback_passwordStrength($password) {

  // NOTE: "SSL: Fatal Protocol Error" occurring
  // echo file_get_contents('https://www.google.com/accounts/RatePassword?Passwd=' . $password);

  // NOTE: google will return 1-4

  // check for invalid password
  if (strlen($password)==0 || !$password) {
    echo 1;
    die;
  }

  // using CURL to fetch website result
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, 'https://www.google.com/accounts/RatePassword?Passwd=' . urlencode($password));
  curl_exec($ch);
  curl_closE($ch);

  die;

}
?>

The next part is modifying the user edit form using the form_alter hook.

<?php
function MYMODULE_form_alter($form_id, &$form) {
  // ...code...
  if ($form_id == 'user_edit') {

    // add weights to current account form elements
    if (isset($form['account']['name'])) $form['account']['name']['#weight'] = 1;
    if (isset($form['account']['mail'])) $form['account']['mail']['#weight'] = 2;
    if (isset($form['account']['pass'])) $form['account']['pass']['#weight'] = 3;
    if (isset($form['account']['status'])) $form['account']['status']['#weight'] = 5;
    if (isset($form['account']['roles'])) $form['account']['roles']['#weight'] = 6;

    // create html for password meter
    $passwordMeterHtml = "
      <div id='passwordMeterFormItem' class='form-item'>
        <label>
          <span id='passwordStrengthLabel'>Password Strength:</span>
          <span id='passwordStrengthDescription'></span>
        </label>
        <table id='passwordMeter'>
          <tr>
            <td id='barLeft'></td>
            <td id='barRight'></td>
          </tr>
        </table>
      </div>
    ";

    // add form "element"
    $form['account']['passwordMeter'] = array(
      '#value' => $passwordMeterHtml,
      '#weight' => 4,
    );

    // add js to password input
    $js = "
      $(document).ready(function(){
        $('form#user-edit #edit-pass-pass1').keyup(function(e){

          if (this.value.length) {
            $.ajax({
              type: 'GET',
              url: '/passwordStrength/' + this.value,
              success: function(passwordCode){
                switch (passwordCode) {
                  case '1':
                    word = 'Weak';
                    break;
                  case '2':
                    word = 'Fair';
                    break;
                  case '3':
                    word = 'Good';
                    break;
                  case '4':
                    word = 'Strong';
                    break;
                }

                // remove td classes
                $('table#passwordMeter td#barLeft').removeClass();
                $('table#passwordMeter td#barRight').removeClass();

                // add td classes
                $('table#passwordMeter td#barLeft').addClass(word);
                $('table#passwordMeter td#barRight').addClass(word);

                // set description
                $('span#passwordStrengthDescription').html(word);
                $('span#passwordStrengthDescription').removeClass();
                $('span#passwordStrengthDescription').addClass(word);
              }
            });
          } else {
            // remove td classes
            $('table#passwordMeter td#barLeft').removeClass();
            $('table#passwordMeter td#barRight').removeClass();

            // set description
            $('span#passwordStrengthDescription').html('');
            $('span#passwordStrengthDescription').removeClass();
          }
        });
      });
    ";
    drupal_add_js($js, 'inline');

  }
  // ...code...
}
?>

Lastly, I added some CSS:

div#passwordMeterFormItem {
  width: 210px;
}

table#passwordMeter {
  width: 100%;
  height: 10px;
  margin: 0;
  clear: both;
}

span#passwordStrengthLabel {
  float: left;
}

table#passwordMeter tbody, table#passwordMeter tr {
  border: none;
}

table#passwordMeter td {
  padding: 0;
  height: 10px;
}

table#passwordMeter td#barLeft {
  background-color: #e0e0e0;
  width: 0%;
}

table#passwordMeter td#barRight {
  background-color: #e0e0e0;
  width: 100%;
}

table#passwordMeter td#barLeft.Weak {
  width: 25%;
  background-color: #AA0033;
}

table#passwordMeter td#barRight.Weak {
  width: 75%;
}

table#passwordMeter td#barLeft.Fair {
  width: 50%;
  background-color: #FFCC33;
}

table#passwordMeter td#barRight.Fair {
  width: 50%;
}

table#passwordMeter td#barLeft.Good {
  width: 75%;
  background-color: #6699CC;
}

table#passwordMeter td#barRight.Good {
  width: 25%;
}

table#passwordMeter td#barLeft.Strong {
  width: 100%;
  background-color: #008000;
}

table#passwordMeter td#barRight.Strong {
  width: 0%;
}

span#passwordStrengthDescription {
  display: block;
  float: right;
}

span#passwordStrengthDescription.Weak {
  color: #AA0033;
}

span#passwordStrengthDescription.Fair {
  color: #FFCC33;
}

span#passwordStrengthDescription.Good {
  color: #6699CC;
}

span#passwordStrengthDescription.Strong {
  color: #008000;
}

Here’s a screen shot:

password strength

Updated: