This patch changes the preprocess hook of the captcha API a bit to add support for multi widget captcha challenges.
The preprocess hook now gets passed all submitted form values, so it can pick the ones he needs.
I added documention about this in captcha_api.txt.

I also changed the tripple quotes to < ?php ... ? > .

CommentFileSizeAuthor
betterapi_7_0.patch5.53 KBsoxofaan

Comments

soxofaan’s picture

from http://drupal.org/node/158613#comment-291998:

Although I tested this with reCAPTCHA (it uses preprocess) and seems to work with it, I'm still not entirely sure why it's required. Could you provide a test case?

Take a captcha challenge like "which word does not belong to the list?", where you show five words and the user has to pick the one that does not belong there.
This challenge can easily be 'gamed' by spammers: just pick a random one of the list and they get 20% successful spam submission. A simple solution would be to take a list of 10 words, where only 10% of spam would get through.

A better solution would be to offer two (or more) lists and the user would have to pick a word from each list. With two lists of five words (10 words in total like in the previous simple solution) only 4% (100% / (5*5)) of spam would get through. With three lists of three words (9 words in total) you would get 3.7%. You get the point.
To do this (in a usable way, for example with radio buttons), you need more than one form item (e.g. 'captcha_response_list1', 'captcha_response_list2', ...).

The point is to make the captcha API more future-proof by offering a powerful preprocess hook, so we wouldn't have to make a new captcha API next year ;) .

soxofaan’s picture

For a real test case: the "which word does not belong to the list?" challenge is now implemented as "Word list captcha" in my freshly created http://drupal.org/project/captcha_pack. It would be nice if I could extend that challenge to multiple lists, as discussed in #1.

robloach’s picture

Remember that this is an API and it's not good to change it in order to make other things work with it. There must be a way around it.....

For example, could you have it preprocess the validation and check the values yourself. Is it possible to use $captcha_response as an array in order to hold multiple values.... These are not solutions, they're just my brainstorming ways around not changing the API to tend to one problem.

soxofaan’s picture

Remember that this is an API and it's not good to change it ...

Well, for captcha v3 we are already changing the catcha API and severely breaking backward compatibility in the process. The addition I propose in not so severe as the changes that are already commited. The preprocess hook was already available, but I think nobody used that, so changing it seems ok.
If you are bothered by changing the existing hook "preprocess", I could also add a new hook like "collect" or something, which wouldn't break anything.

... in order to make other things work with it.

not changing the API to tend to one problem

It's not that I just want to change the API for making other things work with it or solve just one problem. It's about making the new API powerful/future proof enough. We can't predict now what sort of captcha challenges will be invented during the intended lifetime of the captcha module.

If you look at my patch, you'll notice that I change just about two lines in captcha.module (one move and one change). All the other content of the patch is about API documentation. It's not a big change codewise.

check the values yourself.

That is only possible if the captcha challenge impementation can get all the form_values they want, which is not possible now. You only get $form_values['captcha_response']. And letting the captcha challenge modules validate the answer themselves seems just the opposite of having an API.

Is it possible to use $captcha_response as an array in order to hold multiple values

$captcha_response comes straight from the user's browser, so you don't have that much of control over that. That is just the idea behind my patch: make it possible to preprocess the form_values and construct for example an array to overcome the current limitation of the "one string" response.

robloach’s picture

Priority: Normal » Critical

Wundo, mind reviewing this one? Didn't seem to break in my tests.... I haven't tested it recently though. Does it still apply, sox?

robloach’s picture

Status: Needs review » Needs work

This patch needs to be recreated as it conflicts with the captcha/CAPTCHA patch that was just committed.

robloach’s picture

I'm still kind of foggy on how this would work still as well. In 'generate', you could have $result['form']['captcha_challenge'] set to a fieldset, and get the values of your own textfield and selection list within that fieldset through 'preprocess'.... Is 'collect' needed when 'preprocess' could do its work?

case 'generate':
if ($captcha_type == 'mycustomcaptcha') {
$result['preprocess'] = TRUE; // tell captcha to preprocess the form
$result['solution'] = TRUE; // require TRUE to be returned

// ...

case 'preprocess':
// Get the value from the textfield and combo box and validate the two

// If they both validate correctly, then return TRUE.
if($textfield == $combobox){
  return TRUE;
}

Can't you do it that way?

soxofaan’s picture

Status: Needs work » Closed (won't fix)

This feature request is not needed anymore
there are better ways to solve this (e.g. defining a form element with hook_elements() and doing custom processing)
the CAPTCHA API should be kept simple

soxofaan’s picture