Index: captcha.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/captcha/captcha.admin.inc,v
retrieving revision 1.27
diff -u -b -u -p -r1.27 captcha.admin.inc
--- captcha.admin.inc	19 Jun 2009 13:04:00 -0000	1.27
+++ captcha.admin.inc	21 Jun 2009 18:48:02 -0000
@@ -154,11 +154,15 @@ function captcha_admin_settings() {
   }
 
   // Option for case sensitive/insensitive validation of the responses.
-  $form['captcha_case_sensitive_validation'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Case sensitive validation'),
-    '#description' => t('Disable this option to ignore uppercase/lowercase errors in the response.'),
-    '#default_value' => variable_get('captcha_case_sensitive_validation', TRUE),
+  $form['captcha_default_validation'] = array(
+    '#type' => 'radios',
+    '#title' => t('Default validation'),
+    '#description' => t('Define how the response should be processed by default. Modules that implement the actual challenge can override or ignore this.'),
+    '#options' => array(
+      CAPTCHA_DEFAULT_VALIDATION_CASE_SENSITIVE => t('Case sensitive validation: the response has to exactly match the solution.'),
+      CAPTCHA_DEFAULT_VALIDATION_CASE_INSENSITIVE => t('Case insensitive validation: lowercase/uppercase errors are ignored.'),
+    ),
+    '#default_value' => variable_get('captcha_default_validation', CAPTCHA_DEFAULT_VALIDATION_CASE_INSENSITIVE),
   );
 
   // Field for CAPTCHA persistence.
@@ -278,7 +282,7 @@ function captcha_admin_settings_submit($
     }
   }
 
-  variable_set('captcha_case_sensitive_validation', $form_state['values']['captcha_case_sensitive_validation']);
+  variable_set('captcha_default_validation', $form_state['values']['captcha_default_validation']);
   variable_set('captcha_persistence', $form_state['values']['captcha_persistence']);
   variable_set('captcha_log_wrong_responses', $form_state['values']['captcha_log_wrong_responses']);
 
Index: captcha.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/captcha/captcha.module,v
retrieving revision 1.95
diff -u -b -u -p -r1.95 captcha.module
--- captcha.module	21 Jun 2009 18:46:15 -0000	1.95
+++ captcha.module	21 Jun 2009 18:48:02 -0000
@@ -19,6 +19,9 @@ define('CAPTCHA_STATUS_UNSOLVED', 0);
 define('CAPTCHA_STATUS_SOLVED', 1);
 define('CAPTCHA_STATUS_EXAMPLE', 2);
 
+define('CAPTCHA_DEFAULT_VALIDATION_CASE_SENSITIVE', 0);
+define('CAPTCHA_DEFAULT_VALIDATION_CASE_INSENSITIVE', 1);
+
 /**
  * Implementation of hook_help().
  */
@@ -155,7 +158,7 @@ function captcha_cron() {
  */
 function captcha_elements() {
   // Define the CAPTCHA form element with default properties.
-  return array('captcha' => array(
+  $captcha_element = array(
     '#input' => TRUE,
     '#process' => array('captcha_process'),
     // The type of challenge: e.g. 'default', 'none', 'captcha/Math', 'image_captcha/Image', ...
@@ -163,7 +166,14 @@ function captcha_elements() {
     '#default_value' => '',
     // CAPTCHA in admin mode: presolve the CAPTCHA and always show it (despite previous successful responses).
     '#captcha_admin_mode' => FALSE,
-  ));
+    // The default CAPTCHA validation function.
+    '#captcha_validate' => 'captcha_validate_strict_equality',
+  );
+  // Override the default CAPTCHA validation function for case insensitive validation.
+  if (CAPTCHA_DEFAULT_VALIDATION_CASE_INSENSITIVE == variable_get('captcha_default_validation', CAPTCHA_DEFAULT_VALIDATION_CASE_INSENSITIVE)) {
+    $captcha_element['#captcha_validate'] = 'captcha_validate_case_insensitive_equality';
+  }
+  return array('captcha' => $captcha_element);
 }
 
 /**
@@ -216,11 +226,16 @@ function captcha_process($element, $edit
     // Add form elements from challenge as children to CAPTCHA form element.
     $element['captcha_widgets'] = $captcha['form'];
 
+    // Add a validation callback for the CAPTCHA form element (when not in admin mode).
     if (!$element['#captcha_admin_mode']) {
-      // Add a validation callback for the CAPTCHA form element.
       $element['#element_validate'] = array('captcha_validate');
     }
 
+    // Set a custom CAPTCHA validate function if requested.
+    if (isset($captcha['captcha_validate'])) {
+      $element['#captcha_validate'] = $captcha['captcha_validate'];
+    }
+
     // Add pre_render callback for additional CAPTCHA processing.
     $element['#pre_render'] = array('captcha_pre_render_process');
 
@@ -348,6 +363,26 @@ function captcha_form_alter(&$form, $for
 }
 
 /**
+ * CAPTCHA validation function to tests strict equality.
+ * @param $solution the solution of the test.
+ * @param $response the response to the test.
+ * @return TRUE when strictly equal, FALSE otherwise.
+ */
+function captcha_validate_strict_equality($solution, $response) {
+  return $solution === $response;
+}
+
+/**
+ * CAPTCHA validation function to tests case insensitive equality.
+ * @param $solution the solution of the test.
+ * @param $response the response to the test.
+ * @return TRUE when case insensitive equal, FALSE otherwise.
+ */
+function captcha_validate_case_insensitive_equality($solution, $response) {
+  return strtolower($solution) === strtolower($response);
+}
+
+/**
  * CAPTCHA validation handler.
  *
  * This function is placed in the main captcha.module file to make sure that
@@ -380,13 +415,13 @@ function captcha_validate($element, &$fo
     form_set_error('captcha', t('CAPTCHA test failed (unknown csid).'));
   }
   else {
-    // In case of case insensitive validation: convert solution and response to lower case.
-    if (!variable_get('captcha_case_sensitive_validation', TRUE)) {
-      $solution = strtolower($solution);
-      $captcha_response = strtolower($captcha_response);
+    // Get CAPTCHA validate function or fall back on strict equality.
+    $captcha_validate = $element['#captcha_validate'];
+    if (!function_exists($captcha_validate)) {
+       $captcha_validate = 'captcha_validate_strict_equality';
     }
-    // Check answer.
-    if ($captcha_response == $solution) {
+    // Check the response.
+    if ($captcha_validate($solution, $captcha_response)) {
       // Correct answer.
       $_SESSION['captcha_success_form_ids'][$form_id] = $form_id;
       // Record success.
Index: captcha.test
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/captcha/captcha.test,v
retrieving revision 1.12
diff -u -b -u -p -r1.12 captcha.test
--- captcha.test	26 May 2009 21:55:25 -0000	1.12
+++ captcha.test	21 Jun 2009 18:48:03 -0000
@@ -135,14 +135,14 @@ class CapchaTestCase extends DrupalWebTe
     // Log in as normal user.
     $this->drupalLogin($this->normal_user);
 
-    // Test case sensitive posting (the default)
-    variable_set('captcha_case_sensitive_validation', TRUE);
+    // Test case sensitive posting.
+    variable_set('captcha_default_validation', CAPTCHA_DEFAULT_VALIDATION_CASE_SENSITIVE);
     $this->assertCommentPosting('Test 123', TRUE, 'Case sensitive validation of right casing.');
     $this->assertCommentPosting('test 123', FALSE, 'Case sensitive validation of wrong casing.');
     $this->assertCommentPosting('TEST 123', FALSE, 'Case sensitive validation of wrong casing.');
 
     // Test case insensitive posting (the default)
-    variable_set('captcha_case_sensitive_validation', FALSE);
+    variable_set('captcha_default_validation', CAPTCHA_DEFAULT_VALIDATION_CASE_INSENSITIVE);
     $this->assertCommentPosting('Test 123', TRUE, 'Case insensitive validation of right casing.');
     $this->assertCommentPosting('test 123', TRUE, 'Case insensitive validation of wrong casing.');
     $this->assertCommentPosting('TEST 123', TRUE, 'Case insensitive validation of wrong casing.');
Index: image_captcha/image_captcha.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/captcha/image_captcha/image_captcha.module,v
retrieving revision 1.25
diff -u -b -u -p -r1.25 image_captcha.module
--- image_captcha/image_captcha.module	14 May 2009 22:47:38 -0000	1.25
+++ image_captcha/image_captcha.module	21 Jun 2009 18:48:03 -0000
@@ -162,7 +162,7 @@ function image_captcha_captcha($op, $cap
 
         // Handle the case insesitivity option and change the code to lower case
         // before saving it as solution.
-        if (variable_get('captcha_case_sensitive_validation', TRUE)) {
+        if (CAPTCHA_DEFAULT_VALIDATION_CASE_SENSITIVE == variable_get('captcha_default_validation', CAPTCHA_DEFAULT_VALIDATION_CASE_INSENSITIVE)) {
           $description = t('Enter the characters shown in the image. Ignore spaces and be careful about upper and lower case.');
         }
         else {
