Drupal caches pages for anonumous users.
Anonumous users require CAPTCHA more than others. When the same page was loaded for the second, third, etc. time another captcha image is generated but it is not displayed because page was cached by Drupal.

Easy to reproduce: just enable CAPTCHA for registration page, click create a new account and then press F5 several times. This happens because [base URL]?q=user/register record is in the cache table. If you remove it and refresh the page a new captcha image will be displayed correctly.

How can this problem be resolved ? May be it is better to create a file with CAPTCHA image but not generate it through menu callback function ?

Thanks.

Comments

luperry’s picture

hmm... I'm expericing the same issue.

m3avrck’s picture

Captcha module needs to define a hook_init() so it can clear the user/register cache in those cases. Code would be as follows:


/**
 * Implementation of hook_init().
 *
 * We place this hook in it's own module because hook_init() forces the whole module to load
 * this can be a performance hit depending on the size of the module, so we place in it's own
 * module for super fast loading
 */
function mc_image_captcha_init() {
  global $base_root;
  
  // note arg(0) is not yet available yet, so we have to use $_GET
  if ($_GET['q'] == 'user/register') {
    // clear the cache for this page since we are using image captcha and if a user reloads
    // it should show a new image, not a cached one
    db_query("DELETE FROM {cache} WHERE cid = '%s'", $base_root . request_uri());
    
    // since we cleared the cache for this page
    ob_start();
  }
}

ardas’s picture

Thanks for the patch but it doesn't work for me. May be I'm doing anything wrong ...
After I added this code to captcha module I still didn't work, but after I added drupal_set_message() call it began to work .....

I also tried to move the code into captcha_menu() - the result is the same.

ardas’s picture

Dear captcha authors,

Is there any proper fix of this issue ? Are there any abilities to turn on/off caching on a page basis ?

luperry’s picture

here is my workaround to the problem. first I used the cache exclusion hack mentioned here: http://drupal.org/node/23797#comment-75367

then I made the following modifications to textimage.module:

change

function _textimage_image() {
  //if we don't have GD2 functions, we can't generate the image
  if (!function_exists('imagecreatetruecolor')) return;

  // Set headers

to

function _textimage_image() {
  //if we don't have GD2 functions, we can't generate the image
  if (!function_exists('imagecreatetruecolor')) return;

  $GLOBALS['do_not_cache'] = 1;
  // Set headers

change

function textimage_captchachallenge(&$form) {
  $form['captcha_response'] = array (
    '#type' => 'textfield',
    '#title' => t('Captcha Validation'),
    '#default_value' => '',
    '#required' => TRUE,
    '#description' => t('Please type in the letters/numbers that are shown in the image above.'),
    '#prefix' => '<div class="textimage-challenge"><img src="' . url('_textimage/image/' . time()) . '" '.$imageSize[3].' alt="'.t('Captcha Image: you will need to recognize the text in it.').'"/></div>',
  );

  return $form;
}

to

function textimage_captchachallenge(&$form) {
  $form['captcha_response'] = array (
    '#type' => 'textfield',
    '#title' => t('Captcha Validation'),
    '#default_value' => '',
    '#required' => TRUE,
    '#description' => t('Please type in the letters/numbers that are shown in the image above.'),
    '#prefix' => '<div class="textimage-challenge"><img src="' . url('_textimage/image') . '" '.$imageSize[3].' alt="'.t('Captcha Image: you will need to recognize the text in it.').'"/></div>',
  );

  return $form;
}

basically, the workaround uses a fixed url on all the pages, but it makes the image dynamic. not a pretty fix, since you need to hack the drupal core, but it works great. if someone comes up with a better solution, I would love to hear it.

joepublicster’s picture

wundo’s picture

Status: Active » Closed (fixed)