Index: includes/form.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/form.inc,v retrieving revision 1.411 diff -u -p -r1.411 form.inc --- includes/form.inc 1 Dec 2009 16:28:57 -0000 1.411 +++ includes/form.inc 2 Dec 2009 03:06:24 -0000 @@ -1078,7 +1078,7 @@ function form_builder($form_id, $element } // Store a complete copy of the form in form_state prior to building the form. - $form_state['complete form'] = $element; + $form_state['complete form'] = &$element; // Set a flag if we have a correct form submission. This is always TRUE for // programmed forms coming from drupal_form_submit(), or if the form_id coming // from the POST data is set and matches the current form_id. Index: modules/user/user.module =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.module,v retrieving revision 1.1087 diff -u -p -r1.1087 user.module --- modules/user/user.module 1 Dec 2009 16:03:35 -0000 1.1087 +++ modules/user/user.module 2 Dec 2009 10:24:30 -0000 @@ -590,6 +590,68 @@ function user_validate_picture(&$form, & } /** + * This #process is required, because an *element* validation handler cannot add + * a #process for the form (only for $element). + */ +function user_process_current_password($element, &$form_state) { + // Only execute this shit upon crazy shit. + if (!empty($form_state['confirm'])) { + foreach (element_children($element) as $item) { + if (in_array($item, array('form_build_id', 'form_token', 'form_id', 'submit'))) { + continue; + } + $element[$item]['#access'] = FALSE; + } + + $element['user_current_password'] = array( + '#tree' => FALSE, + ); + $element['user_current_password']['help'] = array( + '#markup' => '
' . t('The action you are trying to perform is a bit wacky. Please confirm.') . '
', + ); + $element['user_current_password']['password'] = array( + '#type' => 'password', + '#title' => t('Current password'), + '#description' => t('Turn on your brain-cells to get this done.'), + '#element_validate' => array('user_validate_current_password_confirm'), + ); + } + return $element; +} + +// @todo We need to be able to alter properties in $complete_form. +function user_validate_current_password(&$element, &$form_state, &$complete_form) { + // @todo Only, really, only, trigger this when an *existing* value changed. + $value_changed = (!empty($element['#default_value']) && $element['#default_value'] !== $element['#value']); + if ($value_changed) { + // If the value of this form element changed, we request a rebuild of the + // form, so the confirm form kicks in. + $form_state['rebuild'] = TRUE; + $form_state['confirm'] = TRUE; + + // Backup form input from this submission/request. + $form_state['confirm_input_before'] = $form_state['input']; + $form_state['confirm_values_before'] = $form_state['values']; + } +} + +function user_validate_current_password_confirm(&$element, &$form_state, $complete_form) { + global $user; + + if (user_authenticate($user->name, $form_state['values']['password'])) { + unset($form_state['confirm']); + $form_state['rebuild'] = FALSE; + // Restore form values from previous submission. + // @todo These should already be validated. Really? + $form_state['input'] = $form_state['confirm_input_before']; + $form_state['values'] = $form_state['confirm_values_before']; + } + else { + form_error($element, t('Stupid password. Try again, cowboy.')); + } +} + +/** * Generate a random alphanumeric password. */ function user_password($length = 10) { @@ -902,7 +964,11 @@ function user_account_form(&$form, &$for '#description' => t('A valid e-mail address. All e-mails from the system will be sent to this address. The e-mail address is not made public and will only be used if you wish to receive a new password or wish to receive certain news or notifications by e-mail.'), '#required' => TRUE, '#default_value' => (!$register ? $account->mail : ''), + '#element_validate' => array('user_validate_current_password'), ); + if (!$register) { + $form['#process'][] = 'user_process_current_password'; + } // Display password field only for existing users or when user is allowed to // assign a password during registration.