For those of us that have forms accessible by anonymous users, having a CAPTCHA element would be a great addition. Both XOOPS and ImpressCMS have CAPTCHA classes available for the element and processing - how difficult do you think it would be to implement?
Submitted by Julian Egelstaff on Mon, 01/05/2009 - 2:33pm.
Hello,
That's a very good point. We don't do a lot with anonymous users, but I know some people do. I am not familiar with the captcha classes in XOOPS or ImpressCMS so I don't know exactly how we would implement them, but I can't imagine it's difficult.
The architecture of Formulize 3 should make it pretty easy to deal with this. If you're able to poke around in the PHP code, the places to pay attention to would probably be in the compileElements function of the formdisplay.php file, where the form itself is put together. At the end of that function you could add a captcha element to the form object. And then assuming that the captcha evaluation is available for inspection similarly to how the xoopssecurity class works, you could add a check for it in the readelements.php file, around the same place that the file checks the xoopssecurity token. You could simply put a "return" statement in the file there if the captcha fails, and then nothing would be written to the database. Of course, signifying that to the user so they know the captcha failed, that's another story. But this would be the basic beginnings of how you could implement this.
I will keep a note of this and add it to the roadmap/wishlist. Thanks for suggesting it.
Actually, as I think more about it, you don't really need a form element type, unless you want to customize the element on each form. The simplest way would be to add a module option to enable/disable CAPTCHA on all forms, use the class method to render the element when the form is displayed for a new entry, or if anonymous users are allowed to modify entries, display it then, too.
As you can guess, the class also has a validation method that can be called when the form is submitted and does display an error page if the test fails.
An extended version would be to have an option for each form to enable/disable CAPTCHA, but I don't see a lot of value in that, just that it wouldn't be much more difficult to do and would give more control over each form.
I'll have a look at the files you suggested and see if I can make it work.
Submitted by Julian Egelstaff on Tue, 01/06/2009 - 4:20pm.
Thanks Steve. I would see this as a form by form option, that could be further customized on a screen by screen basis, if you wanted to have a special version of a form that normally has a captcha, but on this one version you don't want a captcha.
When I said you need to add an element, I was talking about the $sform->addElement() part that is in the code you pasted...you have to get that captcha into the form object somehow.
So all in all, this looks very simple to implement, given the code that is above. The one thing I see being a problem though, is that on the redirection, when you redraw the form, you don't have any of the values that the user submitted, so the form will be blank. That's not very friendly for the user. It's hard to get around that, but not impossible.
A reasonably competent PHP programmer should be able to add code similar to the examples here to the compileElements function and the readElements.php file, as I described above, in order to achieve this. In the meantime, I will keep this in the roadmap, it shouldn't be difficult to add something as an option in a future release for those who really need it.
Submitted by Julian Egelstaff on Thu, 02/04/2010 - 10:57am.
Hi Steve,
We are likely going to refactor all the element specific logic into classes. But the timing on that is unknown.
Anyway, yes, it's true that right now, elements get their own file in the admin folder, to handle their element-specific admin UI, and then there's handling for receiving those values in elements_save.php in the admin folder.
There is also element handling in the class/elements.php file, for stuff that is not specific to one element type.
There is then the compileElements function in the the include/formdisplay.php file, and compileElements may modify some data using the loadValue function also in formdisplay.php. And then compileElements invokes the displayElement function from the include/elementdisplay.php file.
And then when the data is submitted by the user, the readelements.php file is invoked once by Formulize to handle all submissions, and that file will refer to the prepDataForWrite function in the include/functions.php file, just to prepare the data for going into the database. The readelements.php file is where the security token is checked, for example, so that is where the captcha check should be verified.
I think it doesn't make sense though, to add the captcha as an element. It's a form level option, or more specifically, it should be a form-screen level option, ie: when you can make form screens, not just list of entries screens, then it would be a feature you turned on or off for each form-screen.
So if it is going to be prototyped into the form now, I would add it as a config option for the form itself. That would mean changes in the admin/mailindex.php (some things are throwbacks still to Formulaire 2.8). That's where the form settings are handled I think, and then there would need to be corresponding changes in the formulize_id database table to capture this one extra on/off setting.
Then there would need to be a change in the compileElements function to add in the captcha to the form, based on this setting. That would be much the same as the code example above.
I hope this braindump is helpful...I'm actually in meetings right now, I can clarify things further if that would help. Let me know.
Thanks again for pursuing this! :-) Let me know if you want commit access to SVN if you don't have it already.
I'll have a look in the form/screen options and see what I can figure out. I definitely could use this option on some of my forms, so I keep coming back to this. :)
hello,
I am currently working on adding a recaptcha, to the forms for my site and looking for a similar solution also, so I thought I would with your permission, 'think out loud' and document my attempts to integrate this. i am using xoops 2.4.4 and forumulize 3.12, on the formulize learning curve, and am amazed at the functionality of this module :) just need this because the majority of the people will be submitting anonymously
for my needs i decided to look at the proxy box to mimic the permissions and form settings, because i want to use it for anon submissions - i looked in mailindex.php mentioned but didn't see where to make the settings change, poked around and found the perms in formindex.php
step one - adding perms to admin/formindex.php - found that group perms are handled there - added add_captcha_entries to perms desc and formulize perm functions. added perms successfully and is now an option on the group perms list as well as updated xoops group_perms table when permissions updated from module
next is obviously adding the recaptcha to the form, in the two include files -
to the formdisplay.php i added:
// add captcha if necessary (only if they have permission and only on new entries, not on edits)
if($gperm_handler->checkRight("add_captcha_entries", $fid, $groups, $mid) AND !$entries[$fid][0]) {
if(!$member_handler) { $member_handler =& xoops_gethandler('member'); }
require_once('recaptchalib.php');
$publickey = 'public key'; // you got this from the signup page
echo recaptcha_get_html($publickey); }
and added OR $add_captcha_entries, to the first form being drawn,
which adds it to the form but no matter where i insert it in the code, it is at the top of the form - currently i have left it under the draw proxy box code because that seems the most logical place for it-
i have tried it in about 15 places and sometimes it adds it to the top of the form, sometimes it just gives me the dreaded white page, and i'm running out of ideas on how to get it to be on the form, directly under where the proxy box is, prior to the bottom submit.
any ideas? formatting didn't seem to work, neither did putting it at the bottom of the compileElements function....
i am more than slightly embarrassed to admit that i cannot see how to format this...
but am going to move on to step 3 while i wait for a response,
STEP 3 - which i don't see me finishing until tomorrow will be to add the check to the readelements file.
i will post the results probably tomorrow, but if anyone has any thoughts in the meantime on the implementation of this i would appreciate the thoughts.
readelements wasn't playing right last night like i thought.
where to put the recaptcha check code? tried it before the security code with the else to continue, and a few other places, in front of all the code, directly in front of the submit/posts code, and i either got a white page or a recaptcha solution error -
i think i maybe needs to be worded a bit different for the formulize, or unhappily it is because formulize's post method is submit/update rather than the straight post which seems to be a conflict of the php captcha method according to the documentation.
or maybe its just i don't know the right way to integrate and close the else statement is what i was thinking last night
maybe instead of the php recaptcha solution i should try the ajax one.
off to keep working on it, and looking for the code for the post method to see if i can integrate it, sorry for rambling, but i am thinking out loud here
Freeform Solutions is proudly supported by a grant from the Ontario Trillium Foundation, which builds healthy and vibrant communities in this great province. The Ontario Trillium Foundation is an agency of the Government of Ontario.
Comments
captchas...not sure...shouldn't be hard
Hello,
That's a very good point. We don't do a lot with anonymous users, but I know some people do. I am not familiar with the captcha classes in XOOPS or ImpressCMS so I don't know exactly how we would implement them, but I can't imagine it's difficult.
The architecture of Formulize 3 should make it pretty easy to deal with this. If you're able to poke around in the PHP code, the places to pay attention to would probably be in the compileElements function of the formdisplay.php file, where the form itself is put together. At the end of that function you could add a captcha element to the form object. And then assuming that the captcha evaluation is available for inspection similarly to how the xoopssecurity class works, you could add a check for it in the readelements.php file, around the same place that the file checks the xoopssecurity token. You could simply put a "return" statement in the file there if the captcha fails, and then nothing would be written to the database. Of course, signifying that to the user so they know the captcha failed, that's another story. But this would be the basic beginnings of how you could implement this.
I will keep a note of this and add it to the roadmap/wishlist. Thanks for suggesting it.
--Julian
CAPTCHA implementation
Actually, as I think more about it, you don't really need a form element type, unless you want to customize the element on each form. The simplest way would be to add a module option to enable/disable CAPTCHA on all forms, use the class method to render the element when the form is displayed for a new entry, or if anonymous users are allowed to modify entries, display it then, too.
As you can guess, the class also has a validation method that can be called when the form is submitted and does display an error page if the test fails.
An extended version would be to have an option for each form to enable/disable CAPTCHA, but I don't see a lot of value in that, just that it wouldn't be much more difficult to do and would give more control over each form.
I'll have a look at the files you suggested and see if I can make it work.
Let you know.
Steve K
CAPTCHA code snippets
Here's a snippet from the imLinks module that uses both the XOOPS and ImpressCMS classes - there is a module config option to enable/disable CAPTCHA.
This is done near the top of the submit page, to validate the test -
if ( $xoopsModuleConfig['captcha'] ) {// Captcha Hack
// Verify entered code
if ( class_exists( 'XoopsFormCaptcha' ) ) {
if ( @include_once ICMS_ROOT_PATH . '/class/captcha/captcha.php' ) {
$xoopsCaptcha = XoopsCaptcha::instance();
if ( ! $xoopsCaptcha -> verify( true ) ) {
redirect_header( 'submit.php', 2, $xoopsCaptcha -> getMessage() );
}
}
} elseif ( class_exists( 'IcmsFormCaptcha' ) ) {
if ( @include_once ICMS_ROOT_PATH . '/class/captcha/captcha.php' ) {
$icmsCaptcha = IcmsCaptcha::instance();
if ( ! $icmsCaptcha -> verify( true ) ) {
redirect_header( 'submit.php', 2, $icmsCaptcha -> getMessage() );
}
}
}
// Captcha Hack
}
This is done at the bottom of the form to render the element -
if ( $xoopsModuleConfig['captcha'] ) {// Captcha Hack
if ( class_exists( 'XoopsFormCaptcha' ) ) {
$sform -> addElement( new XoopsFormCaptcha() );
} elseif ( class_exists( 'IcmsFormCaptcha' ) ) {
$sform -> addElement( new IcmsFormCaptcha() );
}
// Captcha Hack
}
Good examples
Thanks Steve. I would see this as a form by form option, that could be further customized on a screen by screen basis, if you wanted to have a special version of a form that normally has a captcha, but on this one version you don't want a captcha.
When I said you need to add an element, I was talking about the $sform->addElement() part that is in the code you pasted...you have to get that captcha into the form object somehow.
So all in all, this looks very simple to implement, given the code that is above. The one thing I see being a problem though, is that on the redirection, when you redraw the form, you don't have any of the values that the user submitted, so the form will be blank. That's not very friendly for the user. It's hard to get around that, but not impossible.
A reasonably competent PHP programmer should be able to add code similar to the examples here to the compileElements function and the readElements.php file, as I described above, in order to achieve this. In the meantime, I will keep this in the roadmap, it shouldn't be difficult to add something as an option in a future release for those who really need it.
Thanks,
--Julian
RE: Feature request: CAPTCHA
Coming back to this...
Looking through the structure of the module, it appears each element needs a file in /admin - is that correct?
Then, a section in compileElements()
Finally, a way of treating the entry in readelements.php
A few other questions -
How would you handle only displaying the field for a new entry, or when modifying an existing entry?
And, no values need to be stored in the database - is it possible to add a field to a form without creating a corresponding db column?
Steve K
Christian Web Resources
Element structure is in flux, but yes, that's correct
Hi Steve,
We are likely going to refactor all the element specific logic into classes. But the timing on that is unknown.
Anyway, yes, it's true that right now, elements get their own file in the admin folder, to handle their element-specific admin UI, and then there's handling for receiving those values in elements_save.php in the admin folder.
There is also element handling in the class/elements.php file, for stuff that is not specific to one element type.
There is then the compileElements function in the the include/formdisplay.php file, and compileElements may modify some data using the loadValue function also in formdisplay.php. And then compileElements invokes the displayElement function from the include/elementdisplay.php file.
And then when the data is submitted by the user, the readelements.php file is invoked once by Formulize to handle all submissions, and that file will refer to the prepDataForWrite function in the include/functions.php file, just to prepare the data for going into the database. The readelements.php file is where the security token is checked, for example, so that is where the captcha check should be verified.
I think it doesn't make sense though, to add the captcha as an element. It's a form level option, or more specifically, it should be a form-screen level option, ie: when you can make form screens, not just list of entries screens, then it would be a feature you turned on or off for each form-screen.
So if it is going to be prototyped into the form now, I would add it as a config option for the form itself. That would mean changes in the admin/mailindex.php (some things are throwbacks still to Formulaire 2.8). That's where the form settings are handled I think, and then there would need to be corresponding changes in the formulize_id database table to capture this one extra on/off setting.
Then there would need to be a change in the compileElements function to add in the captcha to the form, based on this setting. That would be much the same as the code example above.
I hope this braindump is helpful...I'm actually in meetings right now, I can clarify things further if that would help. Let me know.
Thanks again for pursuing this! :-) Let me know if you want commit access to SVN if you don't have it already.
--Julian
It makes more sense to have captcha as an option, not a field
Thanks for that insight, Julian!
I'll have a look in the form/screen options and see what I can figure out. I definitely could use this option on some of my forms, so I keep coming back to this. :)
Steve K
Christian Web Resources
hmmm
hello,
I am currently working on adding a recaptcha, to the forms for my site and looking for a similar solution also, so I thought I would with your permission, 'think out loud' and document my attempts to integrate this. i am using xoops 2.4.4 and forumulize 3.12, on the formulize learning curve, and am amazed at the functionality of this module :) just need this because the majority of the people will be submitting anonymously
for my needs i decided to look at the proxy box to mimic the permissions and form settings, because i want to use it for anon submissions - i looked in mailindex.php mentioned but didn't see where to make the settings change, poked around and found the perms in formindex.php
step one - adding perms to admin/formindex.php - found that group perms are handled there - added add_captcha_entries to perms desc and formulize perm functions. added perms successfully and is now an option on the group perms list as well as updated xoops group_perms table when permissions updated from module
next is obviously adding the recaptcha to the form, in the two include files -
to the formdisplay.php i added:
// add captcha if necessary (only if they have permission and only on new entries, not on edits)
if($gperm_handler->checkRight("add_captcha_entries", $fid, $groups, $mid) AND !$entries[$fid][0]) {
if(!$member_handler) { $member_handler =& xoops_gethandler('member'); }
require_once('recaptchalib.php');
$publickey = 'public key'; // you got this from the signup page
echo recaptcha_get_html($publickey); }
and added OR $add_captcha_entries, to the first form being drawn,
which adds it to the form but no matter where i insert it in the code, it is at the top of the form - currently i have left it under the draw proxy box code because that seems the most logical place for it-
i have tried it in about 15 places and sometimes it adds it to the top of the form, sometimes it just gives me the dreaded white page, and i'm running out of ideas on how to get it to be on the form, directly under where the proxy box is, prior to the bottom submit.
any ideas? formatting didn't seem to work, neither did putting it at the bottom of the compileElements function....
i am more than slightly embarrassed to admit that i cannot see how to format this...
but am going to move on to step 3 while i wait for a response,
STEP 3 - which i don't see me finishing until tomorrow will be to add the check to the readelements file.
i will post the results probably tomorrow, but if anyone has any thoughts in the meantime on the implementation of this i would appreciate the thoughts.
thanks.
well came back to see, nothing to report
readelements wasn't playing right last night like i thought.
where to put the recaptcha check code? tried it before the security code with the else to continue, and a few other places, in front of all the code, directly in front of the submit/posts code, and i either got a white page or a recaptcha solution error -
i think i maybe needs to be worded a bit different for the formulize, or unhappily it is because formulize's post method is submit/update rather than the straight post which seems to be a conflict of the php captcha method according to the documentation.
or maybe its just i don't know the right way to integrate and close the else statement is what i was thinking last night
maybe instead of the php recaptcha solution i should try the ajax one.
off to keep working on it, and looking for the code for the post method to see if i can integrate it, sorry for rambling, but i am thinking out loud here
Did you get further with recaptcha?
To hack it in, the displayForm function would be the right place, after the call to compileElements I think.
Basically, you would want to add it as another form element to render, so something like this:
$htmlForReCaptcha = "<div id=recaptcha>......</div>";$form->addElement(new xoopsFormLabel('Fill in this captcha', $htmlForReCaptcha));
That should do it. Then to pick it up when the form is submitted, readelements.php is the right place, the values should simply be in $_POST.
Let me know if you would like help with this more. Good luck.
--Julian