Index: captcha.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/captcha/captcha.module,v
retrieving revision 1.75
diff -u -d -u -p -r1.75 captcha.module
--- captcha.module	9 Jan 2009 08:17:24 -0000	1.75
+++ captcha.module	5 Feb 2009 01:44:35 -0000
@@ -215,6 +215,73 @@ function captcha_form_alter(&$form, $for
 }

 /**
+ * Implementation of CAPTCHA validation.
+ *
+ * This function is placed in the main captcha.module file to make sure that
+ * it is available. It is attached to a form by
+ * _captcha_form_alter_untrusted_user() in captcha.pages.inc, but in certain
+ * situations (with cached forms e.g.), captcha_validate() is needed before
+ * captcha.pages.inc is  (already) loaded.
+ */
+function captcha_validate($form, &$form_state) {
+  // Get answer and preprocess if needed
+  $captcha_response = $form_state['values']['captcha_response'];
+  $captcha_info = $form_state['values']['captcha_info'];
+  if ($captcha_info['preprocess']) {
+    $captcha_response = module_invoke($captcha_info['module'], 'captcha', 'preprocess', $captcha_info['type'], $captcha_response);
+  }
+  $form_id = $captcha_info['form_id'];
+  $form_id = $form['form_id']['#value'];
+  // We use $form_state['clicked_button']['#post']['csid']
+  // here instead of $form_state['values']['csid'], because the latter
+  // contains the csid of the new form, while the former contains
+  // the csid of the posted form.
+  $csid = $form_state['clicked_button']['#post']['captcha_sid'];
+
+  $solution = db_result(db_query('SELECT solution FROM {captcha_sessions} WHERE csid = %d AND status = %d', $csid, CAPTCHA_STATUS_UNSOLVED));
+
+  if ($solution === FALSE) {
+    // Unknown challenge_id.
+    form_set_error('captcha', t('CAPTCHA test failed (unknown csid).'));
+  }
+  else {
+    // Check answer.
+    if ($captcha_response == $solution) {
+      // Correct answer.
+      $_SESSION['captcha_success_form_ids'][$form_id] = $form_id;
+      // Record success.
+      db_query("UPDATE {captcha_sessions} SET status=%d, attempts=attempts+1 WHERE csid=%d", CAPTCHA_STATUS_SOLVED, $csid);
+    }
+    else {
+      // Wrong answer.
+      db_query("UPDATE {captcha_sessions} SET attempts=attempts+1 WHERE csid=%d", $csid);
+      // set form error
+      form_set_error('captcha_response', t('The answer you entered for the CAPTCHA was not correct.'));
+      // update wrong response counter
+      variable_set('captcha_wrong_response_counter', variable_get('captcha_wrong_response_counter', 0) + 1);
+      // log to watchdog if needed
+      if (variable_get('captcha_log_wrong_responses', FALSE)) {
+        watchdog('CAPTCHA',
+          '%form_id post blocked by CAPTCHA module: challenge "%challenge" (by module "%module"), user answered "%response", but the solution was "%solution".',
+          array('%form_id' => $form_id,
+            '%response' => $captcha_response, '%solution' => $solution,
+            '%challenge' => $captcha_info['type'], '%module' => $captcha_info['module'],
+          ),
+          WATCHDOG_NOTICE);
+      }
+      // If CAPTCHA was on a login form: stop validating, quit the current request
+      // and forward to the current page (like a reload) to prevent loging in.
+      // We do that because the log in procedure, which happens after
+      // captcha_validate(), does not check error conditions of extra form
+      // elements like the CAPTCHA.
+      if ($form_id == 'user_login' || $form_id == 'user_login_block') {
+        drupal_goto($_GET['q']);
+      }
+    }
+  }
+}
+
+/**
  * Helper function for generating a new CAPTCHA session ID
  */
 function _captcha_generate_captcha_session($status=CAPTCHA_STATUS_UNSOLVED) {
Index: captcha.pages.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/captcha/captcha.pages.inc,v
retrieving revision 1.9
diff -u -d -u -p -r1.9 captcha.pages.inc
--- captcha.pages.inc	10 Jan 2009 16:10:32 -0000	1.9
+++ captcha.pages.inc	5 Feb 2009 01:44:35 -0000
@@ -123,66 +123,6 @@ function _captcha_required_for_user($cap
   return ($captcha_session_status == CAPTCHA_STATUS_UNSOLVED) && !$captcha_persistence_status;
 }

-/**
- * Implementation of form #validate.
- */
-function captcha_validate($form, &$form_state) {
-  // Get answer and preprocess if needed
-  $captcha_response = $form_state['values']['captcha_response'];
-  $captcha_info = $form_state['values']['captcha_info'];
-  if ($captcha_info['preprocess']) {
-    $captcha_response = module_invoke($captcha_info['module'], 'captcha', 'preprocess', $captcha_info['type'], $captcha_response);
-  }
-  $form_id = $captcha_info['form_id'];
-  $form_id = $form['form_id']['#value'];
-  // We use $form_state['clicked_button']['#post']['csid']
-  // here instead of $form_state['values']['csid'], because the latter
-  // contains the csid of the new form, while the former contains
-  // the csid of the posted form.
-  $csid = $form_state['clicked_button']['#post']['captcha_sid'];
-
-  $solution = db_result(db_query('SELECT solution FROM {captcha_sessions} WHERE csid = %d AND status = %d', $csid, CAPTCHA_STATUS_UNSOLVED));
-
-  if ($solution === FALSE) {
-    // Unknown challenge_id.
-    form_set_error('captcha', t('CAPTCHA test failed (unknown csid).'));
-  }
-  else {
-    // Check answer.
-    if ($captcha_response == $solution) {
-      // Correct answer.
-      $_SESSION['captcha_success_form_ids'][$form_id] = $form_id;
-      // Record success.
-      db_query("UPDATE {captcha_sessions} SET status=%d, attempts=attempts+1 WHERE csid=%d", CAPTCHA_STATUS_SOLVED, $csid);
-    }
-    else {
-      // Wrong answer.
-      db_query("UPDATE {captcha_sessions} SET attempts=attempts+1 WHERE csid=%d", $csid);
-      // set form error
-      form_set_error('captcha_response', t('The answer you entered for the CAPTCHA was not correct.'));
-      // update wrong response counter
-      variable_set('captcha_wrong_response_counter', variable_get('captcha_wrong_response_counter', 0) + 1);
-      // log to watchdog if needed
-      if (variable_get('captcha_log_wrong_responses', FALSE)) {
-        watchdog('CAPTCHA',
-          '%form_id post blocked by CAPTCHA module: challenge "%challenge" (by module "%module"), user answered "%response", but the solution was "%solution".',
-          array('%form_id' => $form_id,
-            '%response' => $captcha_response, '%solution' => $solution,
-            '%challenge' => $captcha_info['type'], '%module' => $captcha_info['module'],
-          ),
-          WATCHDOG_NOTICE);
-      }
-      // If CAPTCHA was on a login form: stop validating, quit the current request
-      // and forward to the current page (like a reload) to prevent loging in.
-      // We do that because the log in procedure, which happens after
-      // captcha_validate(), does not check error conditions of extra form
-      // elements like the CAPTCHA.
-      if ($form_id == 'user_login' || $form_id == 'user_login_block') {
-        drupal_goto($_GET['q']);
-      }
-    }
-  }
-}

 /**
  * Implementation of form #pre_render.
