Download & Extend

CAPTCHA fails every time on some forms

Project:CAPTCHA
Version:6.x-2.4
Component:Code
Category:bug report
Priority:critical
Assigned:Unassigned
Status:needs work

Issue Summary

CAPTCHA started to behave strange today. It is working OK on most forms, but one. A that specific form it always blocks, saying, that provided solution was not correct (but it is!). After some debugging I found out, that captcha generates a new CAPTCHA session before checking existing one. "Old" solution then fails with new session.

While researching the problem, I found the problem in captcha_element_process():

<?php
 
list($posted_form_id, $posted_captcha_sid) = _captcha_get_posted_captcha_info($element, $form_state, $this_form_id);
  if (
$this_form_id == $posted_form_id && isset($posted_captcha_sid)) {
   
$captcha_sid = $posted_captcha_sid;
  }
  else {
   
// Generate a new CAPTCHA session if we could not reuse one from a posted form.
   
$captcha_sid = _captcha_generate_captcha_session($this_form_id, CAPTCHA_STATUS_UNSOLVED);
  }
....
?>

it seems like _captcha_get_posted_captcha_info() returns NULL for $posted_form_id. I went down to this function and found out that problem lies in previously determined form and captcha ID, since $form_state['captcha_info']['form_id'] is NULL.

<?php
 
if (isset($form_state['captcha_info'])) {
   
// We already determined the posted form ID and CAPTCHA session ID
    // for this form, so we reuse this info
   
$posted_form_id = $form_state['captcha_info']['form_id'];
   
$posted_captcha_sid = $form_state['captcha_info']['captcha_sid'];
  }
  else {
   
// We have to determine the posted form ID and CAPTCHA session ID
    // from the post data.
    // TODO: is this enough? We had to check more sources in Drupal 6 (see over there).
......
?>

If I baypass prevously determined ID

<?php
 
if (FALSE) {
   
// We already determined the posted form ID and CAPTCHA session ID
    // for this form, so we reuse this info
   
$posted_form_id = $form_state['captcha_info']['form_id'];
   
$posted_captcha_sid = $form_state['captcha_info']['captcha_sid'];
  }
  else {
   
// We have to determine the posted form ID and CAPTCHA session ID
    // from the post data.
    // TODO: is this enough? We had to check more sources in Drupal 6 (see over there).
......
?>

CAPTCHA works fine. I have not found the reason for $form_state['captcha_info']['form_id'] being NULL.

Comments

#1

It is working OK on most forms, but one.

Can you describe the form where it doesn't work? Is it from Drupal Core? From a contrib module? A custom module?

#2

It is a node-edit form. I have a content type, that can be added by anonymous user and then checked and published by editor. Since form is open to the internet i use CAPTCHA to protect it.

#3

i also have captcha (both the default math and reCaptcha) failing every time, but only on a form built with a custom module.
drupal v6.20
captcha 6.x-2.3

this just started happening since the upgrade to 6.20
did something change with 6.20's forms API?

#4

@chadd: please open a separate issue, this issue is about CAPTCHA 7.x-1.x

@slashrsm: what kind of fields are on the node type? Is there perhaps any AJAX involved?

#5

There are Title, Body, 3 text fields and image field. Latter uploads images over AJAX, AFAIK.

It is this form.

http://pogledi.si/node/add/pisma-bralcev

It works now because of fix from Description of this issue.

#6

I forgot about standard tags field.

#7

I'm afraid is the AJAX stuff. (related issue: #918856: CAPTCHA Session Reuse message on forms with AJAX funcionality (e.g. file upload, add another item, ...))
Can you try without the image field?

#8

Priority:normal» major

I have similar problem with comment form. CAPTCHA fails every time.
But it works properly if remove file and image fields from the form.

#9

I ran into the very same problem while having an ajax powered form rendered into a block. After hours of debugging I came to the same conclusion as slashrsm, but I found a different solution:

Find the following lines in the captcha_element_process function:

<?php
 
list($posted_form_id, $posted_captcha_sid) = _captcha_get_posted_captcha_info($element, $form_state, $this_form_id);
  if (
$this_form_id == $posted_form_id && isset($posted_captcha_sid)) {
   
$captcha_sid = $posted_captcha_sid;
  }
  else {
   
// Generate a new CAPTCHA session if we could not reuse one from a posted form.
   
$captcha_sid = _captcha_generate_captcha_session($this_form_id, CAPTCHA_STATUS_UNSOLVED);    
  }             
?>

and change it to:
<?php
 
list($posted_form_id, $posted_captcha_sid) = _captcha_get_posted_captcha_info($element, $form_state, $this_form_id);
  if (
$this_form_id == $posted_form_id && isset($posted_captcha_sid)) {
   
$captcha_sid = $posted_captcha_sid;
  }
  else {
   
// Generate a new CAPTCHA session if we could not reuse one from a posted form.
   
$captcha_sid = _captcha_generate_captcha_session($this_form_id, CAPTCHA_STATUS_UNSOLVED); 
   
   
// set $posted_form_id during the first rendering of the form
   
$posted_form_id = $this_form_id;
  }             
?>

To wrap it up:

  1. set $posted_form_id during initial form render
  2. the hidden field "form_id" will be set with this value
  3. after submitting the form $form_state['captcha_info']['form_id'] will have the form_id stored
  4. ($this_form_id == $posted_form_id) will be true, thus $captcha_sid will stay the same
  5. captcha validation should now be fine

#10

Version:7.x-1.0-alpha2» 7.x-1.x-dev
Priority:major» critical
Status:active» needs review

I'd say this is critical.
Solution #9 works FWIK, so here's a patch.
Please review and commit soon! THX

AttachmentSizeStatusTest resultOperations
1024370_Keep_CAPTCHA_from_failing.patch325.81 KBIdleFAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1024370_Keep_CAPTCHA_from_failing.patch.View details | Re-test

#11

Status:needs review» needs work

The last submitted patch, 1024370_Keep_CAPTCHA_from_failing.patch, failed testing.

#12

Status:needs work» fixed

Solution #9 worked for me.

#13

Status:fixed» needs review

@postscripter: please don't flag this issue as fixed, as long as the fix is not committed yet
@pancho in #10: There is something wrong with your patch: it also contains the removal of all translation files, but those are already removed.

In attachment the reworked patch from #10

AttachmentSizeStatusTest resultOperations
0001-reworked-patch-from-http-drupal.org-node-1024370-com.patch910 bytesIdlePASSED: [[SimpleTest]]: [MySQL] 700 pass(es).View details | Re-test

#14

Oops, something was wrong there. However #13 works fine on our site.

#15

Status:needs review» reviewed & tested by the community

Patch in #13 worked for me.

#16

Patch in #13 worked for me.

#17

Status:reviewed & tested by the community» fixed

Thanks folks, committed.

#18

fyi: this patch is not applied in 7.x-1.0-alpha3; for now either use the dev version or add the change to the alpha3 version..

and another info, this patch solved the issue that the captcha on a user-register form always failed..

greets,
walter

#19

Version:7.x-1.x-dev» 6.x-2.x-dev
Status:fixed» patch (to be ported)

Not fixed in latest 6.x-2.x DEV with Math Captcha added via Form ID to a Mailchimp block...

#20

I am currently stuck on the same problem (Drupal 6.20, Captcha 6.x-2.4). the proposed solutions did not work... Did anyone get captcha to work in a mailchimp form?

#21

It looks like the problem is #tree=true.

With #tree=true, $form_state['values']['captcha_response'] doesn't exist it's something like $form_state['values']['captcha']['captcha_widgets']['captcha_response']

#22

adding
$element['#tree'] = FALSE;
to the captcha_process function seems to fix this.

Here is a patch for 6.x-2.x-dev.

AttachmentSizeStatusTest resultOperations
captcha.patch622 bytesIdleFAILED: [[SimpleTest]]: [MySQL] Invalid patch format in captcha_19.patch.View details | Re-test

#24

#25

#26

commit of patch #13 by #17 should be reverted.
$posted_form_id = $this_form_id makes no sense: there could be multiple forms on same page, but there can only one be posted.

It also breaks things: #1328272: "10 more examples of this challenge"

#27

Status:patch (to be ported)» needs work

as mentioned in #26, I reverted the commit of patch #13:
http://drupalcode.org/project/captcha.git/commit/1161a4d

#28

Version:6.x-2.x-dev» 7.x-1.0-beta1

I seem to have the same problem. when i remove the extra image field the problem is fix. But since im new with drupal codes, im not really sure how to fix this problem with the patch. Maybe a different or easier way for newbies to fix this problem?

#29

Version:7.x-1.0-beta1» 6.x-2.x-dev

@ skitten6: your problem is probably this: #918856: CAPTCHA Session Reuse message on forms with AJAX funcionality (e.g. file upload, add another item, ...)

#30

this issue should be fixed for Drupal 7 version by http://drupalcode.org/project/captcha.git/commit/ef22105

#31

Version:6.x-2.x-dev» 6.x-2.4
Status:needs work» reviewed & tested by the community

testing #22 + #13 against captcha 6.x - 2.4.

anonymous mailchimp works :)

thank you guys. you are a life saver.

btw - changing versions from 2.4 to 2.dev result in empty settings form in the captcha settings. even if you try to add forms to it.

#32

Status:reviewed & tested by the community» needs work

The last submitted patch, captcha.patch, failed testing.